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.

14787 lines
491 KiB

  1. /*
  2. copyright (c) 2018 jones
  3. http://www.apache.org/licenses/LICENSE-2.0
  4. 开源项目 https://github.com/jones2000/HQChart
  5. jones_2000@163.com
  6. 分析家语法编译器
  7. */
  8. //日志
  9. import { JSConsole } from "./umychart.console.wechat.js"
  10. import { JSCommonData } from "./umychart.data.wechat.js"; //行情数据结构体 及涉及到的行情算法(复权,周期等)
  11. import { JSNetwork } from "./umychart.network.wechart.js"
  12. //配色资源
  13. import {
  14. g_JSChartResource,
  15. JSCHART_LANGUAGE_ID,
  16. g_JSChartLocalization,
  17. } from './umychart.resource.wechat.js'
  18. import
  19. {
  20. IFrameSplitOperator,
  21. } from './umychart.framesplit.wechat.js'
  22. import
  23. {
  24. JSIndexScript,
  25. } from './umychart.index.data.wechat.js'
  26. import {
  27. HQ_DATA_TYPE,
  28. ChartData, HistoryData,
  29. SingleData, MinuteData,
  30. } from "./umychart.data.wechat.js";
  31. import
  32. {
  33. g_MinuteCoordinateData,
  34. MARKET_SUFFIX_NAME ,
  35. } from "./umychart.coordinatedata.wechat.js";
  36. var g_JSComplierResource=
  37. {
  38. Domain : "http://127.0.0.1:8080", //API域名
  39. CacheDomain : "http://127.0.0.1:8087", //缓存域名
  40. CustomFunction: //定制函数
  41. {
  42. Data:new Map() //自定义函数 key=函数名, Value:{ID:函数名, Callback: }
  43. },
  44. CustomDataFunction: //自定义数据函数
  45. {
  46. //自定义函数 key=变量名, Value:{ Name:变量名, Description:描述信息, ArgCount:参数个数 }
  47. Data:new Map(
  48. [
  49. [
  50. "L2_VOLNUM",
  51. {
  52. Name:"L2_VOLNUM",
  53. Description:"单数分档,按: N(0--1):(超大+大)/(中+小),M(0--1):买/卖二类,沪深京品种的资金流向,仅日线以上周期,用于特定版本",
  54. ArgCount:2
  55. }
  56. ],
  57. [
  58. "L2_VOL",
  59. {
  60. Name:"L2_VOL",
  61. Description:"成交量分档,按: N(0--3):超大/大/中/小四档处理,M(0--3):买入/卖出/主买/主卖四类,沪深京品种的资金流向,仅日线以上周期,用于特定版本",
  62. ArgCount:2
  63. }
  64. ],
  65. [
  66. "L2_AMO",
  67. {
  68. Name:"L2_AMO",
  69. Description:"成交额分档,按: N(0--3):超大/大/中/小四档处理,M(0--3):买入/卖出/主买/主卖四类,沪深京品种的资金流向,仅日线以上周期,用于特定版本",
  70. ArgCount:2
  71. }
  72. ]
  73. ])
  74. },
  75. CustomVariant: //自定义变量
  76. {
  77. Data:new Map() //自定义函数 key=变量名, Value:{ Name:变量名, Description:描述信息 }
  78. },
  79. IsCustomFunction:function(name)
  80. {
  81. if (g_JSComplierResource.CustomFunction.Data.has(name)) return true;
  82. return false;
  83. },
  84. IsCustomDataFunction:function(name)
  85. {
  86. if (g_JSComplierResource.CustomDataFunction.Data.has(name)) return true;
  87. return false;
  88. },
  89. IsCustomVariant:function(name)
  90. {
  91. if (g_JSComplierResource.CustomVariant.Data.has(name)) return true;
  92. return false;
  93. },
  94. GetDrawTextIcon:function(id)
  95. {
  96. //图标对应的字符代码
  97. let mapIcon=new Map(
  98. [
  99. [1,{Symbol:'↑',Color:'rgb(238,44,44)'} ],[2,{Symbol:'↓',Color:'rgb(0,139,69)'} ],
  100. [3,{Symbol:'😧'} ],[4,{Symbol:'😨'} ],[5,{Symbol:'😁'} ],[6,{Symbol:'😱'} ],
  101. [7,{Symbol:'B',Color:'rgb(238,44,44)'} ],[8,{Symbol:'S',Color:'rgb(0,139,69)'} ],
  102. [9,{Symbol:'💰'} ],[10,{Symbol:'📪'} ],[11,{Symbol:'👆'} ],[12,{Symbol:'👇'} ],
  103. [13,{Symbol:'B',Color:'rgb(178,34,34)'}, ],[14,{Symbol:'S',Color:'rgb(0,139,69)'} ],
  104. [36,{Symbol:'Χ',Color:'rgb(238,44,44)'} ],[37,{Symbol:'X',Color:'rgb(0,139,69)'} ],
  105. [38,{Symbol:'▲',Color:'rgb(238,44,44)'} ],[39,{Symbol:'▼',Color:'rgb(0,139,69)'} ],
  106. [40,{Symbol:'◉',Color:'rgb(238,44,44)'}], [41,{Symbol:'◈',Color:'rgb(238,44,44)'}],
  107. [42,{Symbol:'📌'}], [43,{Symbol:'💎'}], [44,{Symbol:'🥇'}],[45,{Symbol:'🥈'}],[46,{Symbol:'🥉'}],[47,{Symbol:'🏅'}]
  108. ]);
  109. var icon=mapIcon.get(id);
  110. return icon;
  111. },
  112. }
  113. var Messages = {
  114. BadGetterArity: 'Getter must not have any formal parameters',
  115. BadSetterArity: 'Setter must have exactly one formal parameter',
  116. BadSetterRestParameter: 'Setter function argument must not be a rest parameter',
  117. ConstructorIsAsync: 'Class constructor may not be an async method',
  118. ConstructorSpecialMethod: 'Class constructor may not be an accessor',
  119. DeclarationMissingInitializer: 'Missing initializer in %0 declaration',
  120. DefaultRestParameter: 'Unexpected token =',
  121. DuplicateBinding: 'Duplicate binding %0',
  122. DuplicateConstructor: 'A class may only have one constructor',
  123. DuplicateProtoProperty: 'Duplicate __proto__ fields are not allowed in object literals',
  124. ForInOfLoopInitializer: '%0 loop variable declaration may not have an initializer',
  125. GeneratorInLegacyContext: 'Generator declarations are not allowed in legacy contexts',
  126. IllegalBreak: 'Illegal break statement',
  127. IllegalContinue: 'Illegal continue statement',
  128. IllegalExportDeclaration: 'Unexpected token',
  129. IllegalImportDeclaration: 'Unexpected token',
  130. IllegalLanguageModeDirective: 'Illegal \'use strict\' directive in function with non-simple parameter list',
  131. IllegalReturn: 'Illegal return statement',
  132. InvalidEscapedReservedWord: 'Keyword must not contain escaped characters',
  133. InvalidHexEscapeSequence: 'Invalid hexadecimal escape sequence',
  134. InvalidLHSInAssignment: 'Invalid left-hand side in assignment',
  135. InvalidLHSInForIn: 'Invalid left-hand side in for-in',
  136. InvalidLHSInForLoop: 'Invalid left-hand side in for-loop',
  137. InvalidModuleSpecifier: 'Unexpected token',
  138. InvalidRegExp: 'Invalid regular expression',
  139. LetInLexicalBinding: 'let is disallowed as a lexically bound name',
  140. MissingFromClause: 'Unexpected token',
  141. MultipleDefaultsInSwitch: 'More than one default clause in switch statement',
  142. NewlineAfterThrow: 'Illegal newline after throw',
  143. NoAsAfterImportNamespace: 'Unexpected token',
  144. NoCatchOrFinally: 'Missing catch or finally after try',
  145. ParameterAfterRestParameter: 'Rest parameter must be last formal parameter',
  146. Redeclaration: '%0 \'%1\' has already been declared',
  147. StaticPrototype: 'Classes may not have static property named prototype',
  148. StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode',
  149. StrictDelete: 'Delete of an unqualified identifier in strict mode.',
  150. StrictFunction: 'In strict mode code, functions can only be declared at top level or inside a block',
  151. StrictFunctionName: 'Function name may not be eval or arguments in strict mode',
  152. StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode',
  153. StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode',
  154. StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode',
  155. StrictModeWith: 'Strict mode code may not include a with statement',
  156. StrictOctalLiteral: 'Octal literals are not allowed in strict mode.',
  157. StrictParamDupe: 'Strict mode function may not have duplicate parameter names',
  158. StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode',
  159. StrictReservedWord: 'Use of future reserved word in strict mode',
  160. StrictVarName: 'Variable name may not be eval or arguments in strict mode',
  161. TemplateOctalLiteral: 'Octal literals are not allowed in template strings.',
  162. UnexpectedEOS: 'Unexpected end of input',
  163. UnexpectedIdentifier: 'Unexpected identifier',
  164. UnexpectedNumber: 'Unexpected number',
  165. UnexpectedReserved: 'Unexpected reserved word',
  166. UnexpectedString: 'Unexpected string',
  167. UnexpectedTemplate: 'Unexpected quasi %0',
  168. UnexpectedToken: 'Unexpected token %0',
  169. UnexpectedTokenIllegal: 'Unexpected token ILLEGAL',
  170. UnknownLabel: 'Undefined label \'%0\'',
  171. UnterminatedRegExp: 'Invalid regular expression: missing /'
  172. };
  173. var Regex = {
  174. // Unicode v8.0.0 NonAsciiIdentifierStart:
  175. NonAsciiIdentifierStart: /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B4\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309B-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FD5\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AD\uA7B0-\uA7B7\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uF
  176. // Unicode v8.0.0 NonAsciiIdentifierPart:
  177. NonAsciiIdentifierPart: /[\xAA\xB5\xB7\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u08A0-\u08B4\u08E3-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0AF9\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58-\u0C5A\u0C60-\u0C63\u0C66-\u0C6F\u0C81-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D01-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D57\u0D5F-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1369-\u1371\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19DA\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1CD0-\u1CD2\u1CD4-\u1CF6\u1CF8\u1CF9\u1D00-\u1DF5\u1DFC-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u200C\u200D\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3
  178. }
  179. var Character =
  180. {
  181. FromCodePoint: function (cp) {
  182. return (cp < 0x10000) ? String.fromCharCode(cp) :
  183. String.fromCharCode(0xD800 + ((cp - 0x10000) >> 10)) +
  184. String.fromCharCode(0xDC00 + ((cp - 0x10000) & 1023));
  185. },
  186. //是否是空格 https://tc39.github.io/ecma262/#sec-white-space
  187. IsWhiteSpace:function(cp)
  188. {
  189. return (cp === 0x20) || (cp === 0x09) || (cp === 0x0B) || (cp === 0x0C) || (cp === 0xA0) ||
  190. (cp >= 0x1680 && [0x1680, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x202F, 0x205F, 0x3000, 0xFEFF].indexOf(cp) >= 0);
  191. },
  192. //是否换行 https://tc39.github.io/ecma262/#sec-line-terminators
  193. IsLineTerminator:function(cp)
  194. {
  195. return (cp === 0x0A) || (cp === 0x0D) || (cp === 0x2028) || (cp === 0x2029);
  196. },
  197. // https://tc39.github.io/ecma262/#sec-names-and-keywords
  198. IsIdentifierStart:function(cp)
  199. {
  200. return (cp === 0x24) || (cp === 0x5F) ||
  201. (cp >= 0x41 && cp <= 0x5A) ||
  202. (cp >= 0x61 && cp <= 0x7A) ||
  203. (cp === 0x5C) ||
  204. //【】▲▼
  205. (cp===0x3010 || cp===0x3011 || cp===0x25B2 || cp===0x25BC) ||
  206. ((cp >= 0x80) && Regex.NonAsciiIdentifierStart.test(Character.FromCodePoint(cp)));
  207. },
  208. IsIdentifierPart: function (cp)
  209. {
  210. return (cp === 0x24) || (cp === 0x5F) ||
  211. (cp >= 0x41 && cp <= 0x5A) ||
  212. (cp >= 0x61 && cp <= 0x7A) ||
  213. (cp >= 0x30 && cp <= 0x39) ||
  214. (cp === 0x5C) || (cp===0x23) ||
  215. //【】▲▼
  216. (cp===0x3010 || cp===0x3011 || cp===0x25B2 || cp===0x25BC) ||
  217. ((cp >= 0x80) && Regex.NonAsciiIdentifierPart.test(Character.FromCodePoint(cp)));
  218. },
  219. // https://tc39.github.io/ecma262/#sec-literals-numeric-literals
  220. IsDecimalDigit: function (cp)
  221. {
  222. return (cp >= 0x30 && cp <= 0x39); // 0..9
  223. },
  224. IsHexDigit: function (cp)
  225. {
  226. return (cp >= 0x30 && cp <= 0x39) || (cp >= 0x41 && cp <= 0x46) || (cp >= 0x61 && cp <= 0x66); // a..f
  227. },
  228. isOctalDigit: function (cp)
  229. {
  230. return (cp >= 0x30 && cp <= 0x37); // 0..7
  231. }
  232. }
  233. var TOKEN_NAME={};
  234. TOKEN_NAME[1 /* BooleanLiteral */] = 'Boolean';
  235. TOKEN_NAME[2 /* EOF */] = '<end>';
  236. TOKEN_NAME[3 /* Identifier */] = 'Identifier';
  237. TOKEN_NAME[4 /* Keyword */] = 'Keyword';
  238. TOKEN_NAME[5 /* NullLiteral */] = 'Null';
  239. TOKEN_NAME[6 /* NumericLiteral */] = 'Numeric';
  240. TOKEN_NAME[7 /* Punctuator */] = 'Punctuator';
  241. TOKEN_NAME[8 /* StringLiteral */] = 'String';
  242. TOKEN_NAME[9 /* RegularExpression */] = 'RegularExpression';
  243. TOKEN_NAME[10 /* Template */] = 'Template';
  244. //编译异常, 错误类
  245. function ErrorHandler()
  246. {
  247. this.Error=[];
  248. this.RecordError=function(error)
  249. {
  250. this.Error.push(error);
  251. }
  252. this.ConstructError=function(msg,column)
  253. {
  254. let error=new Error(msg);
  255. //通过自己抛异常并自己截获 来获取调用堆栈信息
  256. try
  257. {
  258. throw error;
  259. }
  260. catch(base)
  261. {
  262. if (Object.create && Object.defineProperties)
  263. {
  264. error=Object.create(base);
  265. error.Column=column;
  266. }
  267. }
  268. return error;
  269. }
  270. this.CreateError=function(index, line, col, description)
  271. {
  272. let msg='Line ' + line + ': ' + description;
  273. let error=this.ConstructError(msg,col);
  274. error.Index=index;
  275. error.LineNumber=line;
  276. error.Description=description;
  277. return error;
  278. }
  279. this.ThrowError=function(index, line, col, description)
  280. {
  281. let error=this.CreateError(index,line,col,description);
  282. throw error;
  283. }
  284. }
  285. //扫描类
  286. function Scanner(code, ErrorHandler)
  287. {
  288. this.Source=code;
  289. this.ErrorHandler=ErrorHandler;
  290. this.Length=code.length;
  291. this.Index=0;
  292. this.LineNumber=(code.length>0)?1:0;
  293. this.LineStart=0;
  294. this.CurlyStack=[];
  295. this.SaveState=function() //保存当前扫描状态
  296. {
  297. return { Index:this.Index, LineNumber:this.LineNumber, LineStart:this.LineStart };
  298. }
  299. this.RestoreState=function(state) //还原扫描状态
  300. {
  301. this.Index=state.Index;
  302. this.LineNumber=state.LineNumber;
  303. this.LineStart=state.LineStart;
  304. }
  305. this.IsEOF=function() //否是已经结束
  306. {
  307. return this.Index>=this.Length;
  308. }
  309. this.IsKeyword=function(id)
  310. {
  311. return false;
  312. }
  313. this.CodePointAt = function (i)
  314. {
  315. let cp = this.Source.charCodeAt(i);
  316. if (cp >= 0xD800 && cp <= 0xDBFF)
  317. {
  318. let second = this.Source.charCodeAt(i + 1);
  319. if (second >= 0xDC00 && second <= 0xDFFF) {
  320. var first = cp;
  321. cp = (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000;
  322. }
  323. }
  324. return cp;
  325. }
  326. this.Lex=function()
  327. {
  328. if (this.IsEOF()) return { Type:2/*EOF*/, Value:'', LineNumber:this.LineNumber, LineStart:this.LineStart, Start:this.Index, End:this.Index };
  329. let cp=this.Source.charCodeAt(this.Index);
  330. //变量名 或 关键字
  331. if (Character.IsIdentifierStart(cp)) return this.ScanIdentifier();
  332. //( ) ; 开头 操作符扫描
  333. if (cp === 0x28 || cp === 0x29 || cp === 0x3B) return this.ScanPunctuator();
  334. //' " 开头 字符串扫描
  335. if (cp === 0x27 || cp === 0x22) return this.ScanStringLiteral();
  336. //. 开头 浮点型
  337. if (cp==0x2E)
  338. {
  339. if (Character.IsDecimalDigit(this.Source.charCodeAt(this.Index + 1)))
  340. return this.ScanNumericLiteral();
  341. return this.ScanPunctuator();
  342. }
  343. //数字
  344. if (Character.IsDecimalDigit(cp)) return this.ScanNumericLiteral();
  345. if (cp >= 0xD800 && cp < 0xDFFF)
  346. {
  347. if (Character.IsIdentifierStart(this.CodePointAt(this.Index))) return this.ScanIdentifier();
  348. }
  349. return this.ScanPunctuator();
  350. }
  351. //关键字 变量名 https://tc39.github.io/ecma262/#sec-names-and-keywords
  352. this.ScanIdentifier=function()
  353. {
  354. let type;
  355. let start=this.Index;
  356. //0x5C 反斜杠
  357. let id=(this.Source.charCodeAt(start)=== 0x5C) ? this.GetComplexIdentifier() : this.GetIdentifier();
  358. if (id.length) type=3; //Identifier
  359. else if (this.IsKeyword(id)) type=4; //Keyword
  360. else if (id==null) type=5; //NullLiteral
  361. else if (id=='true' || id=='false') type=1; //BooleanLiteral
  362. else type=3; //Identifier
  363. if (type!=3 && (start+id.length!=this.Index))
  364. {
  365. let restore=this.Index;
  366. this.Index=start;
  367. throw Messages.InvalidEscapedReservedWord;
  368. this.Index=restore;
  369. }
  370. if (id=='AND' || id=='OR') type=7 /*Punctuator*/;
  371. return { Type:type, Value:id, LineNumber:this.LineNumber, LineStart:this.LineStart, Start:start, End:this.Index};
  372. }
  373. this.GetIdentifier=function()
  374. {
  375. let start=this.Index++; //start 保存进来的位置
  376. while(!this.IsEOF())
  377. {
  378. let ch=this.Source.charCodeAt(this.Index);
  379. if (ch==0x5C)
  380. {
  381. this.Index=start;
  382. return this.GetComplexIdentifier();
  383. }
  384. else if (ch >= 0xD800 && ch < 0xDFFF)
  385. {
  386. this.Index=start;
  387. return this.GetComplexIdentifier();
  388. }
  389. if (Character.IsIdentifierPart(ch)) ++this.Index;
  390. else break;
  391. }
  392. return this.Source.slice(start,this.Index);
  393. }
  394. //操作符 https://tc39.github.io/ecma262/#sec-punctuators
  395. this.ScanPunctuator=function()
  396. {
  397. let start=this.Index;
  398. let str=this.Source[this.Index];
  399. switch(str)
  400. {
  401. case '(':
  402. ++this.Index;
  403. break;
  404. case ')':
  405. case ';':
  406. case ',':
  407. ++this.Index;
  408. break;
  409. case '.':
  410. ++this.Index;
  411. /*if (this.Source[this.Index] === '.' && this.Source[this.Index + 1] === '.')
  412. {
  413. //Spread operator: ...
  414. this.Index += 2;
  415. str = '...';
  416. }
  417. */
  418. break;
  419. default:
  420. str=this.Source.substr(this.Index,3);
  421. if (str=='AND')
  422. {
  423. this.Index+=3;
  424. }
  425. else
  426. {
  427. str = this.Source.substr(this.Index, 2);
  428. if (str === '&&' || str === '||' || str === '==' || str === '!=' || str === '<>' || str === '<=' || str === '>=' || str === '=>' || str==':=' || str=='OR')
  429. {
  430. this.Index += 2;
  431. }
  432. else
  433. {
  434. str=this.Source[this.Index];
  435. if ('<>=!+-*%&|^/:'.indexOf(str) >= 0) ++this.Index;
  436. }
  437. }
  438. }
  439. if (this.Index==start)
  440. this.ThrowUnecpectedToken();
  441. return { Type:7/*Punctuator*/, Value:str, LineNumber:this.LineNumber, LineStart:this.LineStart, Start:start, End:this.Index };
  442. }
  443. //字符串 https://tc39.github.io/ecma262/#sec-literals-string-literals
  444. this.ScanStringLiteral=function()
  445. {
  446. let start=this.Index;
  447. let quote=this.Source[this.Index];
  448. ++this.Index;
  449. var octal=false;
  450. let str='';
  451. while(!this.IsEOF())
  452. {
  453. let ch=this.Source[this.Index++];
  454. if (ch==quote)
  455. {
  456. quote='';
  457. break;
  458. }
  459. else if (ch=='\\') //字符串转义
  460. {
  461. throw "not complete";
  462. }
  463. else if (Character.IsLineTerminator(ch.charCodeAt(0)))
  464. {
  465. break;
  466. }
  467. else
  468. {
  469. str+=ch;
  470. }
  471. }
  472. if (quote!='')
  473. {
  474. this.Index=start;
  475. this.ThrowUnecpectedToken();
  476. }
  477. return {Type:8/*StringLiteral*/, Value:str, LineNumber:this.LineNumber, LineStart:this.LineStart, Start:start, End:this.Index};
  478. }
  479. this.ScanNumericLiteral=function()
  480. {
  481. let start=this.Index;
  482. let ch=this.Source[this.Index];
  483. let num='';
  484. if (ch!='.')
  485. {
  486. num=this.Source[this.Index++];
  487. ch=this.Source[this.Index];
  488. // Hex number starts with '0x'. 16进制
  489. if (num=='0')
  490. {
  491. if (ch=='x' || ch=='X')
  492. {
  493. ++this.Index;
  494. return this.ScanHexLiteral(start);
  495. }
  496. }
  497. while(Character.IsDecimalDigit(this.Source.charCodeAt(this.Index)))
  498. {
  499. num+=this.Source[this.Index++];
  500. }
  501. ch=this.Source[this.Index];
  502. }
  503. if (ch=='.')
  504. {
  505. num+=this.Source[this.Index++];
  506. while(Character.IsDecimalDigit(this.Source.charCodeAt(this.Index)))
  507. {
  508. num+=this.Source[this.Index++];
  509. }
  510. ch=this.Source[this.Index];
  511. }
  512. //科学计数法
  513. if (ch=='e' || ch=='E')
  514. {
  515. num+=this.Source[this.Index++];
  516. ch=this.Source[this.Index];
  517. if (ch=='+' || ch=='-') num+=this.Source[this.Index];
  518. if (Character.IsDecimalDigit(this.Source.charCodeAt(this.Index)))
  519. {
  520. while(Character.IsDecimalDigit(this.Source.charCodeAt(this.Index)))
  521. {
  522. num+=this.Source[this.Index++];
  523. }
  524. }
  525. else
  526. {
  527. this.ThrowUnecpectedToken();
  528. }
  529. }
  530. if (Character.IsIdentifierStart(this.Source.charCodeAt(this.Index)))
  531. {
  532. this.ThrowUnecpectedToken();
  533. }
  534. return { Type:6/*NumericLiteral*/, Value:parseFloat(num), LineNumber:this.LineNumber, LineStart:this.LineStart, Start:start, End:this.Index };
  535. }
  536. //空格 或 注释
  537. this.ScanComments=function()
  538. {
  539. let comments;
  540. let start=(this.Index==0);
  541. while(!this.IsEOF())
  542. {
  543. let ch=this.Source.charCodeAt(this.Index);
  544. if (Character.IsWhiteSpace(ch)) //过滤掉空格
  545. {
  546. ++this.Index;
  547. }
  548. else if (Character.IsLineTerminator(ch))
  549. {
  550. ++this.Index;
  551. if (ch==0x0D && this.Source.charCodeAt(this.Index)==0x0A) ++this.Index; //回车+换行
  552. ++this.LineNumber;
  553. this.LineStart=this.Index;
  554. start=true;
  555. }
  556. else if (ch==0x2F) // //注释
  557. {
  558. ch=this.Source.charCodeAt(this.Index+1);
  559. if (ch==0x2F)
  560. {
  561. this.Index+=2;
  562. let comment=this.SkipSingleLineComment(2);
  563. start=true;
  564. }
  565. else
  566. {
  567. break;
  568. }
  569. }
  570. else if (ch == 0x7B) //{ } 注释
  571. {
  572. this.Index += 1;
  573. let comment = this.SkipMultiLineComment();
  574. }
  575. else
  576. {
  577. break;
  578. }
  579. }
  580. return comments;
  581. }
  582. this.SkipMultiLineComment = function ()
  583. {
  584. var comments = [];
  585. while (!this.IsEOF())
  586. {
  587. var ch = this.Source.charCodeAt(this.Index);
  588. if (Character.IsLineTerminator(ch))
  589. {
  590. ++this.LineNumber;
  591. ++this.Index;
  592. this.LineStart = this.Index;
  593. }
  594. else if (ch == 0x7D)
  595. {
  596. this.Index += 1;
  597. return comments;
  598. }
  599. else
  600. {
  601. ++this.Index;
  602. }
  603. }
  604. return comments;
  605. }
  606. //单行注释 https://tc39.github.io/ecma262/#sec-comments
  607. this.SkipSingleLineComment=function(offset)
  608. {
  609. let comments=[];
  610. while(!this.IsEOF())
  611. {
  612. let ch=this.Source.charCodeAt(this.Index);
  613. ++this.Index;
  614. if (Character.IsLineTerminator(ch))
  615. {
  616. if (ch === 13 && this.Source.charCodeAt(this.Index) === 10)
  617. ++this.Index;
  618. ++this.LineNumber;
  619. this.LineStart=this.Index;
  620. return comments;
  621. }
  622. }
  623. return comments;
  624. }
  625. this.ThrowUnecpectedToken=function(message)
  626. {
  627. if (!message) message = Messages.UnexpectedTokenIllegal;
  628. return this.ErrorHandler.ThrowError(this.Index, this.LineNumber, this.Index - this.LineStart + 1, message);
  629. }
  630. }
  631. function Tokenizer(code)
  632. {
  633. this.ErrorHandler=new ErrorHandler(); //错误信息处理类
  634. this.Scanner=new Scanner(code,this.ErrorHandler);
  635. this.Buffer=[];
  636. this.GetNextToken=function()
  637. {
  638. if (this.Buffer.length==0)
  639. {
  640. let comments=this.Scanner.ScanComments();
  641. if (!this.Scanner.IsEOF())
  642. {
  643. let token=this.Scanner.Lex();
  644. let entry={ Type:TOKEN_NAME[token.Type], Value:this.Scanner.Source.slice(token.Start, token.End)};
  645. this.Buffer.push(entry);
  646. }
  647. }
  648. return this.Buffer.shift();
  649. }
  650. }
  651. var Syntax = {
  652. AssignmentExpression: 'AssignmentExpression',
  653. AssignmentPattern: 'AssignmentPattern',
  654. ArrayExpression: 'ArrayExpression',
  655. ArrayPattern: 'ArrayPattern',
  656. ArrowFunctionExpression: 'ArrowFunctionExpression',
  657. AwaitExpression: 'AwaitExpression',
  658. BlockStatement: 'BlockStatement',
  659. BinaryExpression: 'BinaryExpression',
  660. BreakStatement: 'BreakStatement',
  661. CallExpression: 'CallExpression',
  662. CatchClause: 'CatchClause',
  663. ClassBody: 'ClassBody',
  664. ClassDeclaration: 'ClassDeclaration',
  665. ClassExpression: 'ClassExpression',
  666. ConditionalExpression: 'ConditionalExpression',
  667. ContinueStatement: 'ContinueStatement',
  668. DoWhileStatement: 'DoWhileStatement',
  669. DebuggerStatement: 'DebuggerStatement',
  670. EmptyStatement: 'EmptyStatement',
  671. ExportAllDeclaration: 'ExportAllDeclaration',
  672. ExportDefaultDeclaration: 'ExportDefaultDeclaration',
  673. ExportNamedDeclaration: 'ExportNamedDeclaration',
  674. ExportSpecifier: 'ExportSpecifier',
  675. ExpressionStatement: 'ExpressionStatement',
  676. ForStatement: 'ForStatement',
  677. ForOfStatement: 'ForOfStatement',
  678. ForInStatement: 'ForInStatement',
  679. FunctionDeclaration: 'FunctionDeclaration',
  680. FunctionExpression: 'FunctionExpression',
  681. Identifier: 'Identifier',
  682. IfStatement: 'IfStatement',
  683. ImportDeclaration: 'ImportDeclaration',
  684. ImportDefaultSpecifier: 'ImportDefaultSpecifier',
  685. ImportNamespaceSpecifier: 'ImportNamespaceSpecifier',
  686. ImportSpecifier: 'ImportSpecifier',
  687. Literal: 'Literal',
  688. LabeledStatement: 'LabeledStatement',
  689. LogicalExpression: 'LogicalExpression',
  690. MemberExpression: 'MemberExpression',
  691. MetaProperty: 'MetaProperty',
  692. MethodDefinition: 'MethodDefinition',
  693. NewExpression: 'NewExpression',
  694. ObjectExpression: 'ObjectExpression',
  695. ObjectPattern: 'ObjectPattern',
  696. Program: 'Program',
  697. Property: 'Property',
  698. RestElement: 'RestElement',
  699. ReturnStatement: 'ReturnStatement',
  700. SequenceExpression: 'SequenceExpression',
  701. SpreadElement: 'SpreadElement',
  702. Super: 'Super',
  703. SwitchCase: 'SwitchCase',
  704. SwitchStatement: 'SwitchStatement',
  705. TaggedTemplateExpression: 'TaggedTemplateExpression',
  706. TemplateElement: 'TemplateElement',
  707. TemplateLiteral: 'TemplateLiteral',
  708. ThisExpression: 'ThisExpression',
  709. ThrowStatement: 'ThrowStatement',
  710. TryStatement: 'TryStatement',
  711. UnaryExpression: 'UnaryExpression',
  712. UpdateExpression: 'UpdateExpression',
  713. VariableDeclaration: 'VariableDeclaration',
  714. VariableDeclarator: 'VariableDeclarator',
  715. WhileStatement: 'WhileStatement',
  716. WithStatement: 'WithStatement',
  717. YieldExpression: 'YieldExpression'
  718. };
  719. function Node()
  720. {
  721. this.IsNeedIndexData=false; //是否需要大盘数据
  722. this.IsNeedLatestData=false; //是否需要最新的个股行情数据
  723. this.IsNeedSymbolData=false; //是否需要下载股票数据
  724. this.IsNeedMarginData = new Set();
  725. this.IsNeedNewsAnalysisData = new Set(); //新闻统计数据
  726. this.IsNeedBlockIncreaseData = new Set(); //是否需要市场涨跌股票数据统计
  727. this.IsNeedSymbolExData = new Set(); //下载股票行情的其他数据
  728. this.FunctionData=[]; //{ID:, Args:, FunctionName: } FINVALUE(ID),FINONE(ID,Y,MMDD), FINANCE(ID)
  729. this.Dynainfo=[]; //{ID:, Args:, FunctionName: } DYNAINFO()
  730. this.IsAPIData = [] //加载API数据
  731. this.ExecuteIndex=[]; //执行调用指标
  732. this.OtherSymbolData=[]; //其他股票数据 key=股票代码(小写)
  733. this.PeriodSymbolData=[]; //跨周期数据 { Period:, VarName: }
  734. this.ErrorHandler=ErrorHandler;
  735. this.GetDataJobList=function() //下载数据任务列表
  736. {
  737. let jobs=[];
  738. if (this.IsNeedSymbolData) jobs.push({ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SYMBOL_DATA});
  739. if (this.IsNeedIndexData) jobs.push({ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_INDEX_DATA});
  740. //最新的个股行情数据
  741. for(var i=0;i<this.Dynainfo.length;++i)
  742. {
  743. var item=this.Dynainfo[i];
  744. jobs.push(item);
  745. }
  746. //涨跌停家数统计
  747. for (var blockSymbol of this.IsNeedBlockIncreaseData)
  748. {
  749. jobs.push({ ID: JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_INDEX_INCREASE_DATA, Symbol: blockSymbol });
  750. }
  751. //加载融资融券
  752. for (var jobID of this.IsNeedMarginData)
  753. {
  754. jobs.push({ID:jobID});
  755. }
  756. //加载新闻统计
  757. for (var jobID of this.IsNeedNewsAnalysisData)
  758. {
  759. jobs.push({ID:jobID});
  760. }
  761. for (var i in this.IsAPIData)
  762. {
  763. var item = this.IsAPIData[i];
  764. jobs.push(item);
  765. }
  766. for(var i in this.ExecuteIndex)
  767. {
  768. var item=this.ExecuteIndex[i];
  769. jobs.push(item);
  770. }
  771. //行情其他数据
  772. for (var jobID of this.IsNeedSymbolExData)
  773. {
  774. jobs.push({ ID:jobID });
  775. }
  776. for(var i in this.FunctionData)
  777. {
  778. var item=this.FunctionData[i];
  779. jobs.push(item);
  780. }
  781. for(var i in this.OtherSymbolData)
  782. {
  783. var item=this.OtherSymbolData[i];
  784. jobs.push(item);
  785. }
  786. return jobs;
  787. }
  788. this.VerifySymbolVariable = function (varName, token)
  789. {
  790. let setIndexName = new Set(['INDEXA', 'INDEXC', 'INDEXH', 'INDEXL', "INDEXO", "INDEXV", 'INDEXDEC', 'INDEXADV']);
  791. if (setIndexName.has(varName))
  792. {
  793. this.IsNeedIndexData=true;
  794. return;
  795. }
  796. let setSymbolDataName=new Set(['CLOSE','C','VOL','V','OPEN','O','HIGH','H','LOW','L','AMOUNT']);
  797. if (setSymbolDataName.has(varName))
  798. {
  799. this.IsNeedSymbolData=true;
  800. return;
  801. }
  802. if (varName === 'VOLR')
  803. {
  804. if (!this.IsNeedSymbolExData.has(JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_VOLR_DATA))
  805. this.IsNeedSymbolExData.add(JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_VOLR_DATA);
  806. return;
  807. }
  808. //CAPITAL流通股本(手), EXCHANGE 换手率, TOTALCAPITAL 总股本(手)
  809. let setVariantName=new Set(
  810. [
  811. "CAPITAL","TOTALCAPITAL","EXCHANGE",
  812. "HYBLOCK","DYBLOCK","GNBLOCK","FGBLOCK","ZSBLOCK","ZHBLOCK","ZDBLOCK","HYZSCODE",
  813. "GNBLOCKNUM","FGBLOCKNUM","ZSBLOCKNUM","ZHBLOCKNUM","ZDBLOCKNUM",
  814. "HYSYL","HYSJL","FROMOPEN",
  815. //资金流向
  816. "LARGEINTRDVOL","LARGEOUTTRDVOL",
  817. "TRADENUM","TRADEINNUM","TRADEOUTNUM",
  818. "LARGETRDINNUM","LARGETRDOUTNUM",
  819. "CUR_BUYORDER","CUR_SELLORDER",
  820. "ACTINVOL","ACTOUTVOL",
  821. "BIDORDERVOL","BIDCANCELVOL","AVGBIDPX",
  822. "OFFERORDERVOL","OFFERCANCELVOL","AVGOFFERPX",
  823. ]);
  824. if (setVariantName.has(varName))
  825. {
  826. var item={ ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_VARIANT, VariantName:varName };
  827. if (token) item.Token={ Index:token.Start, Line:token.LineNumber };
  828. this.FunctionData.push(item);
  829. return;
  830. }
  831. if (g_JSComplierResource.IsCustomVariant(varName)) //自定义函数
  832. {
  833. var item={ VariantName:varName, ID:JS_EXECUTE_JOB_ID.JOB_CUSTOM_VARIANT_DATA };
  834. if (token) item.Token={ Index:token.Start, Line:token.LineNumber };
  835. this.FunctionData.push(item);
  836. return;
  837. }
  838. }
  839. this.VerifySymbolFunction = function (callee, args, token)
  840. {
  841. //自定义函数 可以覆盖系统内置函数
  842. if (g_JSComplierResource.IsCustomFunction(callee.Name))
  843. {
  844. var item={FunctionName:callee.Name, ID:JS_EXECUTE_JOB_ID.JOB_CUSTOM_FUNCTION_DATA, Args:args}
  845. if (token) item.Token={ Index:token.Start, Line:token.LineNumber};
  846. this.FunctionData.push(item);
  847. return;
  848. }
  849. //自定义数据函数
  850. if (g_JSComplierResource.IsCustomDataFunction(callee.Name))
  851. {
  852. var item={FunctionName:callee.Name, ID:JS_EXECUTE_JOB_ID.JOB_CUSTOM_DATA_FUNCTION, Args:args}
  853. if (token) item.Token={ Index:token.Start, Line:token.LineNumber};
  854. this.FunctionData.push(item);
  855. return;
  856. }
  857. if (callee.Name=='DYNAINFO')
  858. {
  859. var item={ ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SYMBOL_LATEST_DATA, Args:args, FunctionName:callee.Name };
  860. this.Dynainfo.push(item);
  861. return;
  862. }
  863. //财务函数
  864. if (callee.Name=='FINANCE')
  865. {
  866. var item={ ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_FINANCE, Args:args, FunctionName:callee.Name };
  867. if (token) item.Token={ Index:token.Start, Line:token.LineNumber };
  868. this.FunctionData.push(item);
  869. return;
  870. }
  871. if (callee.Name=="FINVALUE")
  872. {
  873. var item={ ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_FINVALUE, Args:args, FunctionName:callee.Name };
  874. if (token) item.Token={ Index:token.Start, Line:token.LineNumber };
  875. this.FunctionData.push(item);
  876. return;
  877. }
  878. if (callee.Name=="FINONE")
  879. {
  880. var item={ ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_FINONE, Args:args, FunctionName:callee.Name };
  881. if (token) item.Token={ Index:token.Start, Line:token.LineNumber };
  882. this.FunctionData.push(item);
  883. return;
  884. }
  885. //专业财务数据
  886. for(var i=0;i<JS_ARRAY_PROFESSIONAL_FINANCE.length;++i)
  887. {
  888. var financeItem=JS_ARRAY_PROFESSIONAL_FINANCE[i];
  889. if (financeItem.Name==callee.Name)
  890. {
  891. var item={ ID:financeItem.JobID, Args:args, FunctionName:callee.Name };
  892. if (token) item.Token={ Index:token.Start, Line:token.LineNumber };
  893. this.FunctionData.push(item);
  894. return;
  895. }
  896. }
  897. if (callee.Name === 'MARGIN')
  898. {
  899. let jobID = JS_EXECUTE_JOB_ID.GetMarginJobID(args[0].Value);
  900. if (jobID && !this.IsNeedMarginData.has(jobID)) this.IsNeedMarginData.add(jobID);
  901. return;
  902. }
  903. if (callee.Name === 'NEWS')
  904. {
  905. let jobID = JS_EXECUTE_JOB_ID.GetNewsAnalysisID(args[0].Value);
  906. if (jobID && !this.IsNeedNewsAnalysisData.has(jobID)) this.IsNeedNewsAnalysisData.add(jobID);
  907. return;
  908. }
  909. if (callee.Name == 'COST' || callee.Name == 'WINNER' || callee.Name=='PWINNER') //筹码都需要换手率
  910. {
  911. //下载流通股
  912. var item={ ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_FINANCE, Args:[7], FunctionName:"FINANCE", FunctionName2:callee.Name };
  913. if (token) item.Token={ Index:token.Start, Line:token.LineNumber };
  914. this.FunctionData.push(item);
  915. return;
  916. }
  917. if (callee.Name=="INBLOCK")
  918. {
  919. var item={ ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_VARIANT, VariantName:"INBLOCK" }; //下载所有板块
  920. if (token) item.Token={ Index:token.Start, Line:token.LineNumber };
  921. this.FunctionData.push(item);
  922. return;
  923. }
  924. if (callee.Name === 'BETA') //beta需要下载上证指数
  925. {
  926. this.IsNeedIndexData = true;
  927. return;
  928. }
  929. if (callee.Name == 'UPCOUNT' || callee.Name == 'DOWNCOUNT') //上涨下跌个数
  930. {
  931. var blockSymbol = args[0].Value;
  932. if (!this.IsNeedBlockIncreaseData.has(blockSymbol)) this.IsNeedBlockIncreaseData.add(blockSymbol);
  933. return;
  934. }
  935. if (callee.Name=='STKINDI' || callee.Name=='CALCSTOCKINDEX') //指标调用
  936. {
  937. var item={ ID:JS_EXECUTE_JOB_ID.JOB_EXECUTE_INDEX, Args:args, FunctionName:callee.Name };
  938. if (token) item.Token={ Index:token.Start, Line:token.LineNumber };
  939. this.ExecuteIndex.push(item);
  940. return;
  941. }
  942. if (callee.Type==Syntax.Literal) //指标调用 "MA.MA1"(10,5,5)"
  943. {
  944. var item={ ID:JS_EXECUTE_JOB_ID.JOB_EXECUTE_INDEX, Args:args, FunctionName:callee.Value, DynamicName:callee.Value };
  945. if (token) item.Token={ Index:token.Start, Line:token.LineNumber };
  946. this.ExecuteIndex.push(item);
  947. return;
  948. }
  949. if (callee.Name == "LOADAPIDATA") //加载API数据
  950. {
  951. var item = { Name: callee.Name, ID: JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_CUSTOM_API_DATA, Args: args };
  952. if (token) item.Token = { Index: token.Start, Line: token.LineNumber };
  953. this.IsAPIData.push(item);
  954. return;
  955. }
  956. let setStockDataName=new Set(['CLOSE',"C",'VOL','V','OPEN','O','HIGH','H','LOW','L','AMOUNT','AMO','VOLINSTK']);
  957. if (setStockDataName.has(callee.Name))
  958. {
  959. var item= { Name:callee.Name, ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_OTHER_SYMBOL_DATA,Args:args };
  960. if (token) item.Token={ Index:token.Start, Line:token.LineNumber};
  961. this.OtherSymbolData.push(item);
  962. return;
  963. }
  964. }
  965. this.VerifySymbolLiteral=function(value,token)
  966. {
  967. if (IFrameSplitOperator.IsString(value))
  968. {
  969. if (value.indexOf('$')>0)
  970. {
  971. var aryValue=value.split('$');
  972. if (aryValue.length!=2) return;
  973. var item= { Literal:value, ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_OTHER_SYMBOL_DATA };
  974. if (token) item.Token={ Index:token.Start, Line:token.LineNumber };
  975. this.OtherSymbolData.push(item);
  976. }
  977. }
  978. }
  979. this.ExpressionStatement=function(expression)
  980. {
  981. return { Type:Syntax.ExpressionStatement, Expression:expression };
  982. }
  983. this.Script=function(body)
  984. {
  985. return {Type:Syntax.Program, Body:body, SourceType:'通达信脚本' };
  986. }
  987. this.SequenceExpression=function(expression)
  988. {
  989. return {Type:Syntax.SequenceExpression, Expression:expression };
  990. }
  991. this.BinaryExpression=function(operator, left, right)
  992. {
  993. let logical = (operator === '||' || operator === '&&' || operator=='AND' || operator=='OR');
  994. let type = logical ? Syntax.LogicalExpression : Syntax.BinaryExpression;
  995. return { Type:type, Operator:operator, Left:left, Right:right };
  996. }
  997. this.Literal=function(value,raw,token)
  998. {
  999. this.VerifySymbolLiteral(value, token);
  1000. return { Type:Syntax.Literal, Value:value, Raw:raw };
  1001. }
  1002. this.Identifier = function (name, token)
  1003. {
  1004. this.VerifySymbolVariable(name, token);
  1005. return { Type:Syntax.Identifier, Name:name};
  1006. }
  1007. this.AssignmentExpression=function (operator, left, right)
  1008. {
  1009. return { Type:Syntax.AssignmentExpression, Operator:operator, Left:left, Right:right };
  1010. }
  1011. //成员变量, 不需要检测
  1012. this.MemberIdentifier=function(name, token)
  1013. {
  1014. return { Type:Syntax.Identifier, Name:name};
  1015. }
  1016. this.UnaryExpression=function(operator, argument)
  1017. {
  1018. return { Type:Syntax.UnaryExpression, Operator:operator, Argument:argument, Prefix:true };
  1019. }
  1020. this.EmptyStatement=function()
  1021. {
  1022. return { Type:Syntax.EmptyStatement };
  1023. }
  1024. this.CallExpression = function (callee, args, token)
  1025. {
  1026. this.VerifySymbolFunction(callee, args, token);
  1027. return { Type:Syntax.CallExpression, Callee:callee, Arguments:args };
  1028. }
  1029. this.StaticMemberExpression = function (object, property,token)
  1030. {
  1031. this.VerifyMemberVariable(object,property, token);
  1032. return { Type: Syntax.MemberExpression, Computed: false, Object: object, Property: property };
  1033. }
  1034. this.VerifyMemberVariable=function(object,property,token)
  1035. {
  1036. var item={ ID:JS_EXECUTE_JOB_ID.JOB_EXECUTE_INDEX, Member:{Object:object, Property:property} };
  1037. if (token) item.Token={ Index:token.Start, Line:token.LineNumber };
  1038. this.ExecuteIndex.push(item);
  1039. return;
  1040. }
  1041. }
  1042. function JSParser(code)
  1043. {
  1044. this.ErrorHandler=new ErrorHandler();
  1045. this.Scanner=new Scanner(code, this.ErrorHandler);
  1046. this.Node=new Node(); //节点创建
  1047. this.LookAhead={Type:2, Value:'', LineNumber:this.Scanner.LineNumber, LineStart:0, Start:0, End:0 };
  1048. this.HasLineTerminator=false;
  1049. this.Context = {
  1050. IsModule: false,
  1051. await: false,
  1052. allowIn: true,
  1053. allowStrictDirective: true,
  1054. allowYield: true,
  1055. FirstCoverInitializedNameError: null,
  1056. IsAssignmentTarget: false,
  1057. IsBindingElement: false,
  1058. InFunctionBody: false,
  1059. inIteration: false,
  1060. inSwitch: false,
  1061. labelSet: {},
  1062. Strict: false
  1063. };
  1064. this.PeratorPrecedence =
  1065. {
  1066. ')': 0,
  1067. ';': 0,
  1068. ',': 0,
  1069. ']': 0,
  1070. '||': 1,
  1071. 'OR':1,
  1072. '&&': 2,
  1073. 'AND':2,
  1074. '|': 3,
  1075. '^': 4,
  1076. '&': 5,
  1077. '=': 6,
  1078. '==': 6,
  1079. '!=': 6,
  1080. '<>': 6,
  1081. '===': 6,
  1082. '!==': 6,
  1083. '<': 7,
  1084. '>': 7,
  1085. '<=': 7,
  1086. '>=': 7,
  1087. '<<': 8,
  1088. '>>': 8,
  1089. '>>>': 8,
  1090. '+': 9,
  1091. '-': 9,
  1092. '*': 11,
  1093. '/': 11,
  1094. '%': 11
  1095. };
  1096. this.StartMarker={Index:0, Line: this.Scanner.LineNumber, Column:0 };
  1097. this.LastMarker={Index:0, Line: this.Scanner.LineNumber, Column:0 };
  1098. this.Initialize=function()
  1099. {
  1100. this.NextToken();
  1101. this.LastMarker={ Index:this.Scanner.Index, Line:this.Scanner.LineNumber, Column:this.Scanner.Index-this.Scanner.LineStart };
  1102. }
  1103. this.CreateNode=function()
  1104. {
  1105. return { Index:this.StartMarker.Index, Line:this.StartMarker.Line, Column:this.StartMarker.Column };
  1106. }
  1107. this.StartNode=function(token, lastLineStart)
  1108. {
  1109. if (lastLineStart==void 0) { lastLineStart=0; }
  1110. let column = token.Start - token.LineStart;
  1111. let line = token.LineNumber;
  1112. if (column < 0)
  1113. {
  1114. column += lastLineStart;
  1115. line--;
  1116. }
  1117. return { Index: token.Start, Line: line, Column: column };
  1118. }
  1119. this.Match=function(value)
  1120. {
  1121. return this.LookAhead.Type==7 /*Punctuator*/ && this.LookAhead.Value==value;
  1122. }
  1123. this.Expect=function(value)
  1124. {
  1125. let token=this.NextToken();
  1126. if (token.Type!=7 /*Punctuator*/ || token.Value!=value)
  1127. this.ThrowUnexpectedToken(token);
  1128. }
  1129. //是否是赋值操作符
  1130. this.MatchAssign=function()
  1131. {
  1132. if (this.LookAhead.Type!=7 /*Punctuator*/) return false;
  1133. let op=this.LookAhead.Value;
  1134. return op==':' || op==':=';
  1135. }
  1136. this.GetTokenRaw=function(token)
  1137. {
  1138. return this.Scanner.Source.slice(token.Start, token.End);
  1139. }
  1140. this.NextToken=function()
  1141. {
  1142. let token=this.LookAhead;
  1143. this.LastMarker.Index=this.Scanner.Index;
  1144. this.LastMarker.Line=this.Scanner.LineNumber;
  1145. this.LastMarker.Column=this.Scanner.Index-this.Scanner.LineStart;
  1146. this.CollectComments(); //过滤注释 空格
  1147. if (this.Scanner.Index !== this.StartMarker.Index)
  1148. {
  1149. this.StartMarker.Index = this.Scanner.Index;
  1150. this.StartMarker.Line = this.Scanner.LineNumber;
  1151. this.StartMarker.Column = this.Scanner.Index - this.Scanner.LineStart;
  1152. }
  1153. let next=this.Scanner.Lex();
  1154. this.HasLineTerminator=(token.LineNumber!=next.LineNumber);
  1155. if (next && this.Context.Strict && next.Type==3/*Identifier */)
  1156. {
  1157. //TODO:
  1158. }
  1159. this.LookAhead=next;
  1160. return token;
  1161. }
  1162. this.CollectComments=function()
  1163. {
  1164. this.Scanner.ScanComments();
  1165. }
  1166. this.ParseScript=function()
  1167. {
  1168. let node=this.CreateNode();
  1169. let body=this.ParseDirectivePrologues();
  1170. while(this.LookAhead.Type!=2 /*EOF*/)
  1171. {
  1172. body.push(this.ParseStatementListItem())
  1173. }
  1174. return this.Finalize(node,this.Node.Script(body));
  1175. }
  1176. //https://tc39.github.io/ecma262/#sec-directive-prologues-and-the-use-strict-directive
  1177. this.ParseDirective=function()
  1178. {
  1179. let token=this.LookAhead;
  1180. let node=this.CreateNode();
  1181. let expr=this.ParseExpression();
  1182. }
  1183. this.ParseDirectivePrologues=function()
  1184. {
  1185. let firstRestricted=null;
  1186. let body=[];
  1187. while(true)
  1188. {
  1189. let token=this.LookAhead;
  1190. if (token.Type!=8 /*StringLiteral*/) break;
  1191. let statement=this.ParseDirective();
  1192. body.push(statement);
  1193. }
  1194. return body;
  1195. }
  1196. // https://tc39.github.io/ecma262/#sec-block
  1197. this.ParseStatementListItem=function()
  1198. {
  1199. let statement;
  1200. this.Context.IsAssignmentTarget=true;
  1201. this.Context.IsBindingElement=true;
  1202. if (this.LookAhead.Type==4 /*Keyword*/)
  1203. {
  1204. }
  1205. else
  1206. {
  1207. statement=this.ParseStatement();
  1208. }
  1209. return statement;
  1210. }
  1211. // https://tc39.github.io/ecma262/#sec-ecmascript-language-statements-and-declarations
  1212. this.ParseStatement=function()
  1213. {
  1214. let statement;
  1215. switch(this.LookAhead.Type)
  1216. {
  1217. case 1 /* BooleanLiteral */:
  1218. case 5 /* NullLiteral */:
  1219. case 6 /* NumericLiteral */:
  1220. case 8 /* StringLiteral */:
  1221. case 10 /* Template */:
  1222. case 9 /* RegularExpression */:
  1223. statement = this.ParseExpressionStatement();
  1224. break;
  1225. case 7 /* Punctuator */:
  1226. let value = this.LookAhead.Value;
  1227. if (value === '(') statement = this.ParseExpressionStatement();
  1228. else if (value === ';') statement = this.ParseEmptyStatement();
  1229. else statement = this.ParseExpressionStatement();
  1230. break;
  1231. case 3 /* Identifier */:
  1232. statement = this.ParseLabelledStatement();
  1233. break;
  1234. case 4 /* Keyword */:
  1235. break;
  1236. default:
  1237. statement="error";
  1238. }
  1239. return statement;
  1240. }
  1241. // https://tc39.github.io/ecma262/#sec-empty-statement
  1242. this.ParseEmptyStatement=function()
  1243. {
  1244. let node=this.CreateNode();
  1245. this.Expect(';');
  1246. return this.Finalize(node, this.Node.EmptyStatement());
  1247. }
  1248. //https://tc39.github.io/ecma262/#sec-labelled-statements
  1249. this.ParseLabelledStatement=function()
  1250. {
  1251. let node=this.CreateNode();
  1252. let expr=this.ParseExpression();
  1253. this.ConsumeSemicolon();
  1254. let statement = new this.Node.ExpressionStatement(expr);
  1255. return this.Finalize(node, statement);
  1256. }
  1257. // https://tc39.github.io/ecma262/#sec-comma-operator
  1258. this.ParseExpression=function()
  1259. {
  1260. let startToken=this.LookAhead;
  1261. let expr=this.IsolateCoverGrammar(this.ParseAssignmentExpression);
  1262. if (this.Match(','))
  1263. {
  1264. let expressions=[];
  1265. expressions.push(expr);
  1266. while(this.LookAhead.Type!=2 /*EOF*/)
  1267. {
  1268. if (!this.Match(',')) break;
  1269. this.NextToken();
  1270. expressions.push(this.IsolateCoverGrammar(this.ParseAssignmentExpression));
  1271. }
  1272. expr=this.Finalize(this.StartNode(startToken),this.Node.SequenceExpression(expressions));
  1273. }
  1274. return expr;
  1275. }
  1276. this.ParseAssignmentExpression=function()
  1277. {
  1278. let expr;
  1279. let startToken=this.LookAhead;
  1280. let token=startToken;
  1281. expr=this.ParseConditionalExpression();
  1282. if (this.MatchAssign())
  1283. {
  1284. if (!this.Context.IsAssignmentTarget)
  1285. {
  1286. let marker=expr.Marker;
  1287. this.ThrowUnexpectedError(marker.Index,marker.Line,marker.Column,Messages.InvalidLHSInAssignment);
  1288. }
  1289. if (!this.Match('=') && !this.Match(':'))
  1290. {
  1291. this.Context.IsAssignmentTarget=false;
  1292. this.Context.IsBindingElement=false;
  1293. }
  1294. else
  1295. {
  1296. this.ReinterpretExpressionAsPattern(expr);
  1297. }
  1298. token=this.NextToken();
  1299. let operator=token.Value;
  1300. let right=this.IsolateCoverGrammar(this.ParseAssignmentExpression);
  1301. expr=this.Finalize(this.StartNode(startToken), this.Node.AssignmentExpression(operator, expr, right));
  1302. this.Context.FirstCoverInitializedNameError=null;
  1303. }
  1304. return expr;
  1305. }
  1306. this.ParseConditionalExpression=function()
  1307. {
  1308. let startToken=this.LookAhead;
  1309. let expr=this.InheritCoverGrammar(this.ParseBinaryExpression);
  1310. return expr;
  1311. }
  1312. this.ParseBinaryExpression=function()
  1313. {
  1314. let startToken=this.LookAhead;
  1315. let expr=this.InheritCoverGrammar(this.ParseExponentiationExpression);
  1316. let token=this.LookAhead;
  1317. var prec=this.BinaryPrecedence(token);
  1318. if (prec>0)
  1319. {
  1320. this.NextToken();
  1321. this.Context.IsAssignmentTarget=false;
  1322. this.Context.IsBindingElement=false;
  1323. let markers=[startToken,this.LookAhead];
  1324. let left=expr;
  1325. let right=this.IsolateCoverGrammar(this.ParseExponentiationExpression);
  1326. let stack=[left,token.Value,right];
  1327. let precedences = [prec];
  1328. while(true)
  1329. {
  1330. prec=this.BinaryPrecedence(this.LookAhead);
  1331. if (prec<=0) break;
  1332. while(stack.length>2 && prec<=precedences[precedences.length-1])
  1333. {
  1334. right=stack.pop();
  1335. let operator=stack.pop();
  1336. precedences.pop();
  1337. left=stack.pop();
  1338. markers.pop();
  1339. let node=this.StartNode(markers[markers.length - 1]);
  1340. stack.push(this.Finalize(node, this.Node.BinaryExpression(operator, left, right)));
  1341. }
  1342. //Shift
  1343. stack.push(this.NextToken().Value);
  1344. precedences.push(prec);
  1345. markers.push(this.LookAhead);
  1346. stack.push(this.IsolateCoverGrammar(this.ParseExponentiationExpression));
  1347. }
  1348. let i=stack.length-1;
  1349. expr=stack[i];
  1350. let lastMarker=markers.pop();
  1351. while(i>1)
  1352. {
  1353. let marker=markers.pop();
  1354. let lastLineStart=lastMarker && lastMarker.LineStart;
  1355. let node=this.StartNode(marker, lastLineStart);
  1356. let operator=stack[i-1];
  1357. expr=this.Finalize(node, this.Node.BinaryExpression(operator, stack[i - 2], expr));
  1358. i-=2;
  1359. lastMarker=marker;
  1360. }
  1361. }
  1362. return expr;
  1363. }
  1364. this.ParseExponentiationExpression=function()
  1365. {
  1366. let startToken=this.LookAhead;
  1367. let expr=this.InheritCoverGrammar(this.ParseUnaryExpression);
  1368. return expr;
  1369. }
  1370. this.ParseUnaryExpression=function()
  1371. {
  1372. let expr;
  1373. if (this.Match('+') || this.Match('-'))
  1374. {
  1375. let node=this.StartNode(this.LookAhead);
  1376. let token=this.NextToken();
  1377. expr=this.InheritCoverGrammar(this.ParseUnaryExpression);
  1378. expr=this.Finalize(node, this.Node.UnaryExpression(token.Value, expr));
  1379. this.Context.IsAssignmentTarget=false;
  1380. this.Context.IsBindingElement=false;
  1381. }
  1382. else
  1383. {
  1384. expr=this.ParseUpdateExpression();
  1385. }
  1386. return expr;
  1387. }
  1388. // https://tc39.github.io/ecma262/#sec-update-expressions
  1389. this.ParseUpdateExpression=function()
  1390. {
  1391. let expr;
  1392. let startToken=this.LookAhead;
  1393. expr=this.InheritCoverGrammar(this.ParseLeftHandSideExpressionAllowCall);
  1394. return expr;
  1395. }
  1396. this.ParseLeftHandSideExpressionAllowCall=function()
  1397. {
  1398. let startToken=this.LookAhead;
  1399. let expr;
  1400. expr=this.InheritCoverGrammar(this.ParsePrimaryExpression);
  1401. while(true)
  1402. {
  1403. if (this.Match('.'))
  1404. {
  1405. this.Context.IsBindingElement = false;
  1406. this.Context.IsAssignmentTarget = true;
  1407. this.Expect('.');
  1408. const property = this.ParseMemberIdentifierName();
  1409. expr = this.Finalize(this.StartNode(startToken), this.Node.StaticMemberExpression(expr, property,startToken));
  1410. }
  1411. else if (this.Match('('))
  1412. {
  1413. this.Context.IsBindingElement=false;
  1414. this.Context.IsAssignmentTarget=false;
  1415. var args=this.ParseArguments(); //解析 调用参数
  1416. expr = this.Finalize(this.StartNode(startToken), this.Node.CallExpression(expr, args, startToken));
  1417. }
  1418. else
  1419. {
  1420. break;
  1421. }
  1422. }
  1423. return expr;
  1424. }
  1425. /*
  1426. BooleanLiteral = 1,
  1427. EOF=2,
  1428. Identifier=3,
  1429. Keyword=4,
  1430. NullLiteral=5,
  1431. NumericLiteral=6,
  1432. Punctuator=7,
  1433. StringLiteral=9,
  1434. RegularExpression=9,
  1435. Template=10
  1436. */
  1437. this.IsIdentifierName = function (token)
  1438. {
  1439. return token.Type === 3 //Identifier
  1440. || token.Type === 4 //Keyword
  1441. || token.Type === 1 //BooleanLiteral
  1442. || token.Type === 5;//NullLiteral;
  1443. }
  1444. this.ParseIdentifierName = function ()
  1445. {
  1446. const node = this.CreateNode();
  1447. const token = this.NextToken();
  1448. if (!this.IsIdentifierName(token))
  1449. {
  1450. this.ThrowUnexpectedToken(token);
  1451. }
  1452. return this.Finalize(node, this.Node.Identifier(token.Value, token));
  1453. }
  1454. this.ParseMemberIdentifierName=function()
  1455. {
  1456. const node = this.CreateNode();
  1457. const token = this.NextToken();
  1458. if (!this.IsIdentifierName(token))
  1459. {
  1460. this.ThrowUnexpectedToken(token);
  1461. }
  1462. return this.Finalize(node, this.Node.MemberIdentifier(token.Value, token));
  1463. }
  1464. // https://tc39.github.io/ecma262/#sec-left-hand-side-expressions
  1465. this.ParseArguments=function()
  1466. {
  1467. this.Expect('(');
  1468. var args=[];
  1469. if (!this.Match(')'))
  1470. {
  1471. while(true)
  1472. {
  1473. let expr=this.IsolateCoverGrammar(this.ParseAssignmentExpression);
  1474. args.push(expr);
  1475. if (this.Match(')')) break;
  1476. this.ExpectCommaSeparator();
  1477. if (this.Match(')')) break;
  1478. }
  1479. }
  1480. this.Expect(')');
  1481. return args;
  1482. }
  1483. // Quietly expect a comma when in tolerant mode, otherwise delegates to expect().
  1484. this.ExpectCommaSeparator=function()
  1485. {
  1486. this.Expect(',');
  1487. }
  1488. // https://tc39.github.io/ecma262/#sec-primary-expression
  1489. this.ParsePrimaryExpression=function()
  1490. {
  1491. let node=this.CreateNode();
  1492. let expr;
  1493. var token, raw;
  1494. switch(this.LookAhead.Type)
  1495. {
  1496. case 3:/* Identifier */
  1497. token = this.NextToken();
  1498. expr = this.Finalize(node, this.Node.Identifier(token.Value, token));
  1499. break;
  1500. case 6:/* NumericLiteral */
  1501. case 8:/* StringLiteral */
  1502. this.Context.IsAssignmentTarget=false;
  1503. this.Context.IsBindingElement=false;
  1504. token=this.NextToken();
  1505. raw=this.GetTokenRaw(token);
  1506. expr=this.Finalize(node, this.Node.Literal(token.Value,raw,token));
  1507. break;
  1508. case 7:/* Punctuator */
  1509. switch(this.LookAhead.Value)
  1510. {
  1511. case '(':
  1512. this.Context.IsBindingElement=false;
  1513. expr=this.InheritCoverGrammar(this.ParseGroupExpression);
  1514. break;
  1515. default:
  1516. expr=this.ThrowUnexpectedToken(this.NextToken())
  1517. }
  1518. break;
  1519. default:
  1520. expr = this.ThrowUnexpectedToken(this.NextToken());
  1521. }
  1522. return expr;
  1523. }
  1524. this.ParseGroupExpression=function()
  1525. {
  1526. let expr;
  1527. this.Expect('(');
  1528. if (this.Match(')'))
  1529. {
  1530. this.NextToken();
  1531. }
  1532. else
  1533. {
  1534. let startToken=this.LookAhead;
  1535. let params=[];
  1536. let arrow=false;
  1537. this.Context.IsBindingElement=true;
  1538. expr=this.InheritCoverGrammar(this.ParseAssignmentExpression);
  1539. if (this.Match(','))
  1540. {
  1541. let expressions=[];
  1542. this.Context.IsAssignmentTarget=false;
  1543. expressions.push(expr);
  1544. while(this.LookAhead.Type!=2 /* EOF */)
  1545. {
  1546. if (!this.Match(',')) break;
  1547. this.NextToken();
  1548. if (this.Match(')'))
  1549. {
  1550. }
  1551. }
  1552. }
  1553. if (!arrow)
  1554. {
  1555. this.Expect(')');
  1556. this.Context.IsBindingElement=false;
  1557. }
  1558. }
  1559. return expr;
  1560. }
  1561. // https://tc39.github.io/ecma262/#sec-expression-statement
  1562. this.ParseExpressionStatement=function()
  1563. {
  1564. let node=this.CreateNode();
  1565. let expr=this.ParseExpression();
  1566. this.ConsumeSemicolon();
  1567. return this.Finalize(node,this.Node.ExpressionStatement(expr));
  1568. }
  1569. this.ConsumeSemicolon=function()
  1570. {
  1571. if (this.Match(';'))
  1572. {
  1573. this.NextToken();
  1574. }
  1575. else if (!this.HasLineTerminator)
  1576. {
  1577. //if (this.LookAhead.Type!=2/*EOF*/ && !this.Match('}'))
  1578. this.LastMarker.Index=this.StartMarker.Index;
  1579. this.LastMarker.Line=this.StartMarker.Line;
  1580. this.LastMarker.Column=this.StartMarker.Column;
  1581. }
  1582. }
  1583. this.ReinterpretExpressionAsPattern=function(expr)
  1584. {
  1585. switch(expr.Type)
  1586. {
  1587. case Syntax.Identifier:
  1588. case Syntax.MemberExpression:
  1589. case Syntax.AssignmentExpression:
  1590. break;
  1591. default:
  1592. break;
  1593. }
  1594. }
  1595. this.Finalize=function(marker,node)
  1596. {
  1597. node.Marker={ Line:marker.Line, Column:marker.Column, Index:marker.Index };
  1598. return node;
  1599. }
  1600. this.BinaryPrecedence = function (token)
  1601. {
  1602. let op = token.Value;
  1603. let precedence;
  1604. if (token.Type === 7 /* Punctuator */) precedence = this.PeratorPrecedence[op] || 0;
  1605. else precedence = 0;
  1606. return precedence;
  1607. };
  1608. this.IsolateCoverGrammar=function(parseFunction)
  1609. {
  1610. let previousIsBindingElement=this.Context.IsBindingElement;
  1611. let previousIsAssignmentTarget=this.Context.IsAssignmentTarget;
  1612. let previousFirstCoverInitializedNameError=this.Context.FirstCoverInitializedNameError;
  1613. this.Context.IsBindingElement=true;
  1614. this.Context.IsAssignmentTarget=true;
  1615. this.Context.FirstCoverInitializedNameError=null;
  1616. let result=parseFunction.call(this);
  1617. if (this.Context.FirstCoverInitializedNameError!=null)
  1618. {
  1619. //错误 this.throwUnexpectedToken(this.context.firstCoverInitializedNameError);
  1620. }
  1621. this.Context.IsBindingElement=previousIsBindingElement;
  1622. this.Context.IsAssignmentTarget=previousIsAssignmentTarget;
  1623. this.Context.FirstCoverInitializedNameError=previousFirstCoverInitializedNameError;
  1624. return result;
  1625. }
  1626. this.InheritCoverGrammar = function (parseFunction)
  1627. {
  1628. let previousIsBindingElement = this.Context.IsBindingElement;
  1629. let previousIsAssignmentTarget = this.Context.IsAssignmentTarget;
  1630. let previousFirstCoverInitializedNameError = this.Context.FirstCoverInitializedNameError;
  1631. this.Context.IsBindingElement = true;
  1632. this.Context.IsAssignmentTarget = true;
  1633. this.Context.FirstCoverInitializedNameError = null;
  1634. let result = parseFunction.call(this);
  1635. this.Context.IsBindingElement = this.Context.IsBindingElement && previousIsBindingElement;
  1636. this.Context.IsAssignmentTarget = this.Context.IsAssignmentTarget && previousIsAssignmentTarget;
  1637. this.Context.FirstCoverInitializedNameError = previousFirstCoverInitializedNameError || this.Context.FirstCoverInitializedNameError;
  1638. return result;
  1639. };
  1640. this.ThrowUnexpectedToken=function(token,message)
  1641. {
  1642. throw this.UnexpectedTokenError(token,message);
  1643. }
  1644. this.ThrowUnexpectedError=function(index,line,column,message)
  1645. {
  1646. let msg=message || "执行异常";
  1647. return this.ErrorHandler.ThrowError(index,line,column,msg);
  1648. }
  1649. this.UnexpectedTokenError=function(token,message)
  1650. {
  1651. let msg=message || Messages.UnexpectedToken;
  1652. let value='ILLEGAL';
  1653. if (token)
  1654. {
  1655. if (!message)
  1656. {
  1657. }
  1658. value=token.Value;
  1659. }
  1660. msg=msg.replace("%0",value);
  1661. if (token && typeof(token.LineNumber)=='number')
  1662. {
  1663. let index=token.Start;
  1664. let line=token.LineNumber;
  1665. let lastMarkerLineStart=this.LastMarker.Index-this.LastMarker.Column;
  1666. let column=token.Start-lastMarkerLineStart+1;
  1667. return this.ErrorHandler.CreateError(index,line,column,msg);
  1668. }
  1669. else
  1670. {
  1671. let index=this.LastMarker.Index;
  1672. let line=this.LastMarker.Line;
  1673. let column=this.LastMarker.Column+1;
  1674. return this.ErrorHandler.CreateError(index,line,column,msg);
  1675. }
  1676. }
  1677. }
  1678. /*
  1679. 算法类
  1680. */
  1681. function JSAlgorithm(errorHandler, symbolData)
  1682. {
  1683. this.ErrorHandler=errorHandler;
  1684. this.SymbolData = symbolData; //股票数据
  1685. //相加
  1686. this.Add=function(data,data2)
  1687. {
  1688. let isNumber=typeof(data)=='number';
  1689. let isNumber2=typeof(data2)=='number';
  1690. //单数值相加
  1691. if (isNumber && isNumber2) return data+data2;
  1692. //都是数组相加
  1693. let result=[];
  1694. if (!isNumber && !isNumber2)
  1695. {
  1696. let count=Math.max(data.length, data2.length);
  1697. for(let i=0;i<count;++i)
  1698. {
  1699. result[i]=null; //初始化
  1700. if (i<data.length && i<data2.length)
  1701. {
  1702. if ( this.IsNumber(data[i]) && this.IsNumber(data2[i]) ) result[i]=data[i]+data2[i];
  1703. }
  1704. }
  1705. return result;
  1706. }
  1707. //单数据和数组相加
  1708. let value;
  1709. let aryData;
  1710. if (isNumber)
  1711. {
  1712. value=data;
  1713. aryData=data2;
  1714. }
  1715. else
  1716. {
  1717. value=data2;
  1718. aryData=data;
  1719. }
  1720. for(let i in aryData)
  1721. {
  1722. result[i]=null;
  1723. if (this.IsNumber(aryData[i]) && this.IsNumber(value)) result[i]=value+aryData[i];
  1724. }
  1725. return result;
  1726. }
  1727. //相减
  1728. this.Subtract=function(data,data2)
  1729. {
  1730. let isNumber=typeof(data)=='number';
  1731. let isNumber2=typeof(data2)=='number';
  1732. //单数值相减
  1733. if (isNumber && isNumber2) return data-data2;
  1734. //都是数组相减
  1735. let result=[];
  1736. if (!isNumber && !isNumber2)
  1737. {
  1738. let count=Math.max(data.length, data2.length);
  1739. for(let i=0;i<count;++i)
  1740. {
  1741. result[i]=null; //初始化
  1742. if (i<data.length && i<data2.length)
  1743. {
  1744. if ( this.IsNumber(data[i]) && this.IsNumber(data2[i]) ) result[i]=data[i]-data2[i];
  1745. }
  1746. }
  1747. return result;
  1748. }
  1749. if (isNumber) //单数据-数组
  1750. {
  1751. for(let i in data2)
  1752. {
  1753. result[i]=null;
  1754. if (this.IsNumber(data) && this.IsNumber(data2[i])) result[i]=data-data2[i];
  1755. }
  1756. }
  1757. else //数组-单数据
  1758. {
  1759. for(let i in data)
  1760. {
  1761. result[i]=null;
  1762. if (this.IsNumber(data[i]) && this.IsNumber(data2)) result[i]=data[i]-data2;
  1763. }
  1764. }
  1765. return result;
  1766. }
  1767. //相乘
  1768. this.Multiply=function(data,data2)
  1769. {
  1770. let isNumber=typeof(data)=='number';
  1771. let isNumber2=typeof(data2)=='number';
  1772. //单数值相乘
  1773. if (isNumber && isNumber2) return data*data2;
  1774. //都是数组相乘
  1775. let result=[];
  1776. if (!isNumber && !isNumber2)
  1777. {
  1778. let count=Math.max(data.length, data2.length);
  1779. for(let i=0;i<count;++i)
  1780. {
  1781. result[i]=null; //初始化
  1782. if (i<data.length && i<data2.length)
  1783. {
  1784. if ( this.IsNumber(data[i]) && this.IsNumber(data2[i]) ) result[i]=data[i]*data2[i];
  1785. }
  1786. }
  1787. return result;
  1788. }
  1789. //单数据和数组相乘
  1790. let value;
  1791. let aryData;
  1792. if (isNumber)
  1793. {
  1794. value=data;
  1795. aryData=data2;
  1796. }
  1797. else
  1798. {
  1799. value=data2;
  1800. aryData=data;
  1801. }
  1802. for(let i in aryData)
  1803. {
  1804. result[i]=null;
  1805. if (this.IsNumber(aryData[i]) && this.IsNumber(value)) result[i]=value*aryData[i];
  1806. }
  1807. return result;
  1808. }
  1809. //相除
  1810. this.Divide=function(data,data2)
  1811. {
  1812. let isNumber=typeof(data)=='number';
  1813. let isNumber2=typeof(data2)=='number';
  1814. //单数值相除
  1815. if (isNumber && isNumber2)
  1816. {
  1817. if (data2==0) return null; //除0判断
  1818. return data/data2;
  1819. }
  1820. //都是数组相除
  1821. let result=[];
  1822. if (!isNumber && !isNumber2)
  1823. {
  1824. let count=Math.max(data.length, data2.length);
  1825. for(let i=0;i<count;++i)
  1826. {
  1827. result[i]=null; //初始化
  1828. if (i<data.length && i<data2.length)
  1829. {
  1830. if ( this.IsNumber(data[i]) && this.IsDivideNumber(data2[i]) ) result[i]=data[i]/data2[i];
  1831. }
  1832. }
  1833. return result;
  1834. }
  1835. if (isNumber) //单数据-数组
  1836. {
  1837. for(let i in data2)
  1838. {
  1839. result[i]=null;
  1840. if ( this.IsNumber(data) && this.IsDivideNumber(data2[i]) ) result[i]=data/data2[i];
  1841. }
  1842. }
  1843. else //数组-单数据
  1844. {
  1845. for(let i in data)
  1846. {
  1847. result[i]=null;
  1848. if ( this.IsNumber(data[i]) && this.IsDivideNumber(data2) ) result[i]=data[i]/data2;
  1849. }
  1850. }
  1851. return result;
  1852. }
  1853. //大于
  1854. this.GT=function(data,data2)
  1855. {
  1856. let isNumber=IFrameSplitOperator.IsNumber(data);
  1857. let isNumber2=IFrameSplitOperator.IsNumber(data2);
  1858. //单数值比较
  1859. if (isNumber && isNumber2) return (data>data2 ? 1 : 0);
  1860. //都是数组比较
  1861. let result=[];
  1862. if (Array.isArray(data) && Array.isArray(data2))
  1863. {
  1864. let count=Math.max(data.length, data2.length);
  1865. for(let i=0;i<count;++i)
  1866. {
  1867. result[i]=null; //初始化
  1868. if (i<data.length && i<data2.length)
  1869. {
  1870. if (!IFrameSplitOperator.IsVaild(data[i])) continue;
  1871. if (!IFrameSplitOperator.IsVaild(data2[i])) continue;
  1872. result[i]=(data[i]>data2[i] ? 1:0);
  1873. }
  1874. }
  1875. return result;
  1876. }
  1877. if (isNumber) //单数据-数组
  1878. {
  1879. for(let i in data2)
  1880. {
  1881. result[i]=null;
  1882. if (!IFrameSplitOperator.IsVaild(data)) continue;
  1883. if (!IFrameSplitOperator.IsVaild(data2[i])) continue;
  1884. result[i]=(data>data2[i] ? 1 : 0);
  1885. }
  1886. }
  1887. else //数组-单数据
  1888. {
  1889. for(let i in data)
  1890. {
  1891. result[i]=null;
  1892. if (!IFrameSplitOperator.IsVaild(data[i])) continue;
  1893. if (!IFrameSplitOperator.IsVaild(data2)) continue;
  1894. result[i]=(data[i]>data2 ? 1 : 0);
  1895. }
  1896. }
  1897. return result;
  1898. }
  1899. //大于等于
  1900. this.GTE=function(data,data2)
  1901. {
  1902. let isNumber=IFrameSplitOperator.IsNumber(data);
  1903. let isNumber2=IFrameSplitOperator.IsNumber(data2);
  1904. //单数值比较
  1905. if (isNumber && isNumber2) return (data>=data2 ? 1 : 0);
  1906. //都是数组比较
  1907. let result=[];
  1908. if (Array.isArray(data) && Array.isArray(data2))
  1909. {
  1910. let count=Math.max(data.length, data2.length);
  1911. for(let i=0;i<count;++i)
  1912. {
  1913. result[i]=null; //初始化
  1914. if (i<data.length && i<data2.length)
  1915. {
  1916. if (!IFrameSplitOperator.IsVaild(data[i])) continue;
  1917. if (!IFrameSplitOperator.IsVaild(data2[i])) continue;
  1918. result[i]=(data[i]>=data2[i] ? 1:0);
  1919. }
  1920. }
  1921. return result;
  1922. }
  1923. if (isNumber) //单数据-数组
  1924. {
  1925. for(let i in data2)
  1926. {
  1927. result[i]=null;
  1928. if (!IFrameSplitOperator.IsVaild(data)) continue;
  1929. if (!IFrameSplitOperator.IsVaild(data2[i])) continue;
  1930. result[i]=(data>=data2[i] ? 1 : 0);
  1931. }
  1932. }
  1933. else //数组-单数据
  1934. {
  1935. for(let i in data)
  1936. {
  1937. result[i]=null;
  1938. if (!IFrameSplitOperator.IsVaild(data[i])) continue;
  1939. if (!IFrameSplitOperator.IsVaild(data2)) continue;
  1940. result[i]=(data[i]>=data2 ? 1 : 0);
  1941. }
  1942. }
  1943. return result;
  1944. }
  1945. //小于
  1946. this.LT=function(data,data2)
  1947. {
  1948. let isNumber=IFrameSplitOperator.IsNumber(data);
  1949. let isNumber2=IFrameSplitOperator.IsNumber(data2);
  1950. //单数值比较
  1951. if (isNumber && isNumber2) return (data<data2 ? 1 : 0);
  1952. //都是数组比较
  1953. let result=[];
  1954. if (Array.isArray(data) && Array.isArray(data2))
  1955. {
  1956. let count=Math.max(data.length, data2.length);
  1957. for(let i=0;i<count;++i)
  1958. {
  1959. result[i]=null; //初始化
  1960. if (i<data.length && i<data2.length)
  1961. {
  1962. if (!IFrameSplitOperator.IsVaild(data[i])) continue;
  1963. if (!IFrameSplitOperator.IsVaild(data2[i])) continue;
  1964. result[i]=(data[i]<data2[i] ? 1:0);
  1965. }
  1966. }
  1967. return result;
  1968. }
  1969. if (isNumber) //单数据-数组
  1970. {
  1971. for(let i in data2)
  1972. {
  1973. result[i]=null;
  1974. if (!IFrameSplitOperator.IsVaild(data)) continue;
  1975. if (!IFrameSplitOperator.IsVaild(data2[i])) continue;
  1976. if ( !isNaN(data) && !isNaN(data2[i]) ) result[i]=(data<data2[i] ? 1 : 0);
  1977. }
  1978. }
  1979. else //数组-单数据
  1980. {
  1981. for(let i in data)
  1982. {
  1983. result[i]=null;
  1984. if (!IFrameSplitOperator.IsVaild(data[i])) continue;
  1985. if (!IFrameSplitOperator.IsVaild(data2)) continue;
  1986. result[i]=(data[i]<data2 ? 1 : 0);
  1987. }
  1988. }
  1989. return result;
  1990. }
  1991. //小于等于
  1992. this.LTE=function(data,data2)
  1993. {
  1994. let isNumber=IFrameSplitOperator.IsNumber(data);
  1995. let isNumber2=IFrameSplitOperator.IsNumber(data2);
  1996. //单数值比较
  1997. if (isNumber && isNumber2) return (data>=data2 ? 1 : 0);
  1998. //都是数组比较
  1999. let result=[];
  2000. if (Array.isArray(data) && Array.isArray(data2))
  2001. {
  2002. let count=Math.max(data.length, data2.length);
  2003. for(let i=0;i<count;++i)
  2004. {
  2005. result[i]=null; //初始化
  2006. if (i<data.length && i<data2.length)
  2007. {
  2008. if (!IFrameSplitOperator.IsVaild(data[i])) continue;
  2009. if (!IFrameSplitOperator.IsVaild(data2[i])) continue;
  2010. result[i]=(data[i]<=data2[i] ? 1:0);
  2011. }
  2012. }
  2013. return result;
  2014. }
  2015. if (isNumber) //单数据-数组
  2016. {
  2017. for(let i in data2)
  2018. {
  2019. result[i]=null;
  2020. if (!IFrameSplitOperator.IsVaild(data)) continue;
  2021. if (!IFrameSplitOperator.IsVaild(data2[i])) continue;
  2022. result[i]=(data<=data2[i] ? 1 : 0);
  2023. }
  2024. }
  2025. else //数组-单数据
  2026. {
  2027. for(let i in data)
  2028. {
  2029. result[i]=null;
  2030. if (!IFrameSplitOperator.IsVaild(data[i])) continue;
  2031. if (!IFrameSplitOperator.IsVaild(data2)) continue;
  2032. result[i]=(data[i]<=data2 ? 1 : 0);
  2033. }
  2034. }
  2035. return result;
  2036. }
  2037. //等于
  2038. this.EQ=function(data,data2)
  2039. {
  2040. let isNumber=IFrameSplitOperator.IsNumber(data);
  2041. let isNumber2=IFrameSplitOperator.IsNumber(data2);
  2042. //单数值比较
  2043. if (isNumber && isNumber2) return (data==data2 ? 1 : 0);
  2044. //都是数组比较
  2045. let result=[];
  2046. if (Array.isArray(data) && Array.isArray(data2))
  2047. {
  2048. let count=Math.max(data.length, data2.length);
  2049. for(let i=0;i<count;++i)
  2050. {
  2051. result[i]=null; //初始化
  2052. if (i<data.length && i<data2.length)
  2053. {
  2054. if ( !isNaN(data[i]) && !isNaN(data2[i]) ) result[i]=(data[i]==data2[i] ? 1:0);
  2055. }
  2056. }
  2057. return result;
  2058. }
  2059. if (isNumber) //单数据-数组
  2060. {
  2061. for(let i in data2)
  2062. {
  2063. result[i]=null;
  2064. if ( !isNaN(data) && !isNaN(data2[i]) ) result[i]=(data==data2[i] ? 1 : 0);
  2065. }
  2066. }
  2067. else //数组-单数据
  2068. {
  2069. for(let i in data)
  2070. {
  2071. result[i]=null;
  2072. if ( !isNaN(data[i]) && !isNaN(data2) ) result[i]=(data[i]==data2 ? 1 : 0);
  2073. }
  2074. }
  2075. return result;
  2076. }
  2077. //不等于
  2078. this.NEQ = function (data, data2)
  2079. {
  2080. let isNumber=IFrameSplitOperator.IsNumber(data);
  2081. let isNumber2=IFrameSplitOperator.IsNumber(data2);
  2082. //单数值比较
  2083. if (isNumber && isNumber2) return (data != data2 ? 1 : 0);
  2084. //都是数组比较
  2085. let result = [];
  2086. if (Array.isArray(data) && Array.isArray(data2))
  2087. {
  2088. let count = Math.max(data.length, data2.length);
  2089. for (let i = 0; i < count; ++i)
  2090. {
  2091. result[i] = null; //初始化
  2092. if (i < data.length && i < data2.length)
  2093. {
  2094. if (!isNaN(data[i]) && !isNaN(data2[i])) result[i] = (data[i] != data2[i] ? 1 : 0);
  2095. }
  2096. }
  2097. return result;
  2098. }
  2099. if (isNumber) //单数据-数组
  2100. {
  2101. for (let i in data2)
  2102. {
  2103. result[i] = null;
  2104. if (!isNaN(data) && !isNaN(data2[i])) result[i] = (data != data2[i] ? 1 : 0);
  2105. }
  2106. }
  2107. else //数组-单数据
  2108. {
  2109. for (let i in data)
  2110. {
  2111. result[i] = null;
  2112. if (!isNaN(data[i]) && !isNaN(data2)) result[i] = (data[i] != data2 ? 1 : 0);
  2113. }
  2114. }
  2115. return result;
  2116. }
  2117. //AND &&
  2118. this.And=function(data,data2)
  2119. {
  2120. let isNumber=typeof(data)=='number';
  2121. let isNumber2=typeof(data2)=='number';
  2122. //单数值 &&
  2123. if (isNumber && isNumber2) return (data && data2 ? 1 : 0);
  2124. //都是数组 &&
  2125. let result=[];
  2126. if (!isNumber && !isNumber2)
  2127. {
  2128. let count=Math.max(data.length, data2.length);
  2129. for(let i=0;i<count;++i)
  2130. {
  2131. result[i]=null; //初始化
  2132. if (i<data.length && i<data2.length)
  2133. {
  2134. if ( !isNaN(data[i]) && !isNaN(data2[i]) ) result[i]=(data[i] && data2[i] ? 1:0);
  2135. }
  2136. }
  2137. return result;
  2138. }
  2139. if (isNumber) //单数据-数组
  2140. {
  2141. for(let i in data2)
  2142. {
  2143. result[i]=null;
  2144. if ( !isNaN(data) && !isNaN(data2[i]) ) result[i]=(data && data2[i] ? 1 : 0);
  2145. }
  2146. }
  2147. else //数组-单数据
  2148. {
  2149. for(let i in data)
  2150. {
  2151. result[i]=null;
  2152. if ( !isNaN(data[i]) && !isNaN(data2) ) result[i]=(data[i] && data2 ? 1 : 0);
  2153. }
  2154. }
  2155. return result;
  2156. }
  2157. //OR ||
  2158. this.Or=function(data,data2)
  2159. {
  2160. let isNumber=typeof(data)=='number';
  2161. let isNumber2=typeof(data2)=='number';
  2162. //单数值 &&
  2163. if (isNumber && isNumber2) return (data || data2 ? 1 : 0);
  2164. //都是数组 &&
  2165. let result=[];
  2166. if (!isNumber && !isNumber2)
  2167. {
  2168. let count=Math.max(data.length, data2.length);
  2169. for(let i=0;i<count;++i)
  2170. {
  2171. result[i]=null; //初始化
  2172. if (i<data.length && i<data2.length)
  2173. {
  2174. if ( !isNaN(data[i]) && !isNaN(data2[i]) ) result[i]=(data[i] || data2[i] ? 1:0);
  2175. }
  2176. }
  2177. return result;
  2178. }
  2179. if (isNumber) //单数据-数组
  2180. {
  2181. for(let i in data2)
  2182. {
  2183. result[i]=null;
  2184. if ( !isNaN(data) && !isNaN(data2[i]) ) result[i]=(data || data2[i] ? 1 : 0);
  2185. }
  2186. }
  2187. else //数组-单数据
  2188. {
  2189. for(let i in data)
  2190. {
  2191. result[i]=null;
  2192. if ( !isNaN(data[i]) && !isNaN(data2) ) result[i]=(data[i] || data2 ? 1 : 0);
  2193. }
  2194. }
  2195. return result;
  2196. }
  2197. this.IF=function(data,trueData,falseData)
  2198. {
  2199. let isNumber=this.IsNumber(data);
  2200. let isNumber2=this.IsNumber(trueData);
  2201. let isNumber3=this.IsNumber(falseData);
  2202. var isArray2=Array.isArray(trueData);
  2203. var isArray3=Array.isArray(falseData);
  2204. //单数值
  2205. if (isNumber)
  2206. {
  2207. if (isNumber2 && isNumber3) return data?trueData:falseData;
  2208. return data? trueData:falseData;
  2209. }
  2210. //都是数组
  2211. let result=[];
  2212. for(let i in data)
  2213. {
  2214. if (data[i])
  2215. {
  2216. if (isNumber2) result[i]=trueData;
  2217. else if (isArray2) result[i]=trueData[i];
  2218. else result[i]=null;
  2219. }
  2220. else
  2221. {
  2222. if (isNumber3) result[i]=falseData;
  2223. else if (isArray3) result[i]=falseData[i];
  2224. else result[i]=null;
  2225. }
  2226. }
  2227. return result;
  2228. }
  2229. /*
  2230. 根据条件求不同的值,同IF判断相反.
  2231. 用法: IFN(X,A,B)若X不为0则返回B,否则返回A
  2232. 例如: IFN(CLOSE>OPEN,HIGH,LOW)表示该周期收阴则返回最高值,否则返回最低值
  2233. */
  2234. this.IFN=function(data,trueData,falseData)
  2235. {
  2236. return this.IF(data,falseData,trueData);
  2237. }
  2238. //指标函数 函数名全部大写
  2239. this.REF=function(data,n)
  2240. {
  2241. let result=[];
  2242. if (typeof(n)=='number')
  2243. {
  2244. if (IFrameSplitOperator.IsNumber(data)) //单数值
  2245. {
  2246. if (n<0) return result;
  2247. var kData=this.SymbolData.Data.Data;
  2248. if (!kData || kData.length<=0) return result;
  2249. var count=kData.length;
  2250. for(var i=n;i<count;++i)
  2251. {
  2252. result[i]=data;
  2253. }
  2254. }
  2255. else
  2256. {
  2257. if (data.length<=0) return result;
  2258. if (n>=data.length) return result;
  2259. result=data.slice(0,data.length-n);
  2260. for(let i=0;i<n;++i)
  2261. result.unshift(null);
  2262. }
  2263. }
  2264. else //n 为数组的情况
  2265. {
  2266. for(let i=0;i<data.length;++i)
  2267. {
  2268. result[i]=null;
  2269. if (i>=n.length) continue;
  2270. var value=n[i];
  2271. if (value>0 && value<=i) result[i]=data[i-value];
  2272. else if (i) result[i]=result[i-1];
  2273. else result[i]=data[i];
  2274. }
  2275. }
  2276. return result;
  2277. }
  2278. //引用若干周期前的数据(未作平滑处理).
  2279. //用法: REFV(X,A),引用A周期前的X值.A可以是变量.
  2280. //平滑处理:当引用不到数据时进行的操作.
  2281. //例如: REFV(CLOSE,BARSCOUNT(C)-1)表示第二根K线的收盘价.
  2282. this.REFV=function(data,n)
  2283. {
  2284. let result=[];
  2285. if (typeof(n)=='number')
  2286. {
  2287. if (data.length<=0) return result;
  2288. if (n>=data.length) return result;
  2289. result=data.slice(0,data.length-n);
  2290. for(let i=0;i<n;++i) //不作平滑处理
  2291. result.unshift(null);
  2292. }
  2293. else //n 为数组的情况
  2294. {
  2295. for(let i=0;i<data.length;++i)
  2296. {
  2297. result[i]=null;
  2298. if (i>=n.length) continue;
  2299. var value=n[i];
  2300. if (value>=0 && value<=i) result[i]=data[i-value];
  2301. }
  2302. }
  2303. return result;
  2304. }
  2305. //属于未来函数,引用若干周期后的数据(平滑处理).
  2306. //用法: REFX(X,A),引用A周期后的X值.A可以是变量.
  2307. //平滑处理:当引用不到数据时进行的操作.此函数中,平滑时使用上一个周期的引用值.
  2308. //例如: TT:=IF(C>O,1,2);
  2309. // REFX(CLOSE,TT);表示阳线引用下一周期的收盘价,阴线引用日后第二周期的收盘价.
  2310. this.REFX=function(data,n)
  2311. {
  2312. let result=[];
  2313. if (typeof(n)=='number')
  2314. {
  2315. if (data.length<=0) return result;
  2316. if (n>=data.length) return result;
  2317. result=data.slice(n,data.length);
  2318. //平滑处理
  2319. var lastData=data[data.length-1];
  2320. for(let i=0;i<n;++i)
  2321. result.push(lastData);
  2322. }
  2323. else //n 为数组的情况
  2324. {
  2325. var dataCount=data.length;
  2326. for(let i=0;i<data.length;++i)
  2327. {
  2328. result[i]=null;
  2329. if (i>=n.length) continue;
  2330. var value=n[i];
  2331. if (value>=0 && value+i<dataCount) result[i]=data[i+value];
  2332. else if (i) result[i]=result[i-1];
  2333. else result[i]=data[i];
  2334. }
  2335. }
  2336. return result;
  2337. }
  2338. //属于未来函数,引用若干周期后的数据(未作平滑处理).
  2339. //用法:REFXV(X,A),引用A周期后的X值.A可以是变量.
  2340. //平滑处理:当引用不到数据时进行的操作.
  2341. //例如: REFXV(CLOSE,1)表示下一周期的收盘价,在日线上就是明天收盘价
  2342. this.REFXV=function(data,n)
  2343. {
  2344. let result=[];
  2345. if (typeof(n)=='number')
  2346. {
  2347. if (data.length<=0) return result;
  2348. if (n>=data.length) return result;
  2349. result=data.slice(n,data.length);
  2350. //平滑处理
  2351. for(let i=0;i<n;++i)
  2352. result.push(null);
  2353. }
  2354. else //n 为数组的情况
  2355. {
  2356. var dataCount=data.length;
  2357. for(let i=0;i<data.length;++i)
  2358. {
  2359. result[i]=null;
  2360. if (i>=n.length) continue;
  2361. var value=n[i];
  2362. if (value>=0 && value+i<dataCount) result[i]=data[i+value];
  2363. }
  2364. }
  2365. return result;
  2366. }
  2367. //求最大值.
  2368. //用法:MAX(A,B,C,D ..... ) 返回A,B,C,D ..... 中的较大值
  2369. //例如: MAX(CLOSE-OPEN,0)表示若收盘价大于开盘价返回它们的差值,否则返回0
  2370. this.MAX=function(args, node)
  2371. {
  2372. if (args.length==0) this.ThrowUnexpectedNode(node,'MAX() Error: 参数个数不能为0');
  2373. if (args.length==1) return args[0];
  2374. var aryData=[], aryNumber=[];
  2375. for(var i in args)
  2376. {
  2377. var item=args[i];
  2378. if (IFrameSplitOperator.IsNumber(item)) aryNumber.push(item);
  2379. else if (Array.isArray(item)) aryData.push(item);
  2380. }
  2381. var maxNumber=null;
  2382. if (aryNumber.length>0)
  2383. {
  2384. maxNumber=aryNumber[0];
  2385. for(var i=1; i<aryNumber.length; ++i)
  2386. {
  2387. maxNumber=Math.max(maxNumber,aryNumber[i]);
  2388. }
  2389. }
  2390. var maxAryData=null;
  2391. if (aryData.length>0)
  2392. {
  2393. maxAryData=aryData[0].slice(0);
  2394. for(var i=1;i<aryData.length;++i)
  2395. {
  2396. var dataItem=aryData[i];
  2397. for(var j in dataItem)
  2398. {
  2399. var maxItem=maxAryData[j];
  2400. var item=dataItem[j];
  2401. if (!IFrameSplitOperator.IsNumber(maxItem)) continue;
  2402. if (!IFrameSplitOperator.IsNumber(item))
  2403. {
  2404. maxAryData[j]=null;
  2405. continue;
  2406. }
  2407. maxAryData[j]=Math.max(maxItem,item);
  2408. }
  2409. }
  2410. }
  2411. if (maxAryData==null && maxNumber!=null) return maxNumber;
  2412. if (maxAryData && maxNumber==null) return maxAryData;
  2413. for(var i in maxAryData)
  2414. {
  2415. if (!IFrameSplitOperator.IsNumber(maxAryData[i])) continue;
  2416. maxAryData[i]=Math.max(maxAryData[i],maxNumber);
  2417. }
  2418. return maxAryData;
  2419. }
  2420. //求最小值.
  2421. //用法:MIN(A,B, C, D .....)返回A,B, C ,D ......中的较小值
  2422. //例如:MIN(CLOSE,OPEN)返回开盘价和收盘价中的较小值
  2423. this.MIN=function(args, node)
  2424. {
  2425. if (args.length==0) this.ThrowUnexpectedNode(node,'MIN() Error: 参数个数不能为0');
  2426. if (args.length==1) return args[0];
  2427. var aryData=[], aryNumber=[];
  2428. for(var i in args)
  2429. {
  2430. var item=args[i];
  2431. if (IFrameSplitOperator.IsNumber(item)) aryNumber.push(item);
  2432. else if (Array.isArray(item)) aryData.push(item);
  2433. }
  2434. var minNumber=null;
  2435. if (aryNumber.length>0)
  2436. {
  2437. minNumber=aryNumber[0];
  2438. for(var i=1; i<aryNumber.length; ++i)
  2439. {
  2440. minNumber=Math.min(minNumber,aryNumber[i]);
  2441. }
  2442. }
  2443. var minAryData=null;
  2444. if (aryData.length>0)
  2445. {
  2446. minAryData=aryData[0].slice(0);
  2447. for(var i=1;i<aryData.length;++i)
  2448. {
  2449. var dataItem=aryData[i];
  2450. for(var j in dataItem)
  2451. {
  2452. var minItem=minAryData[j];
  2453. var item=dataItem[j];
  2454. if (!IFrameSplitOperator.IsNumber(minItem)) continue;
  2455. if (!IFrameSplitOperator.IsNumber(item))
  2456. {
  2457. minAryData[j]=null;
  2458. continue;
  2459. }
  2460. minAryData[j]=Math.min(minItem,item);
  2461. }
  2462. }
  2463. }
  2464. if (minAryData==null && minNumber!=null) return minNumber;
  2465. if (minAryData && minNumber==null) return minAryData;
  2466. for(var i in minAryData)
  2467. {
  2468. if (!IFrameSplitOperator.IsNumber(minAryData[i])) continue;
  2469. minAryData[i]=Math.min(minAryData[i],minNumber);
  2470. }
  2471. return minAryData;
  2472. }
  2473. //取正数
  2474. this.ABS=function(data)
  2475. {
  2476. let result=[];
  2477. for(let i in data)
  2478. {
  2479. result[i]=null;
  2480. if (!isNaN(data[i])) result[i]=Math.abs(data[i]);
  2481. }
  2482. return result;
  2483. }
  2484. this.MA=function(data,dayCount)
  2485. {
  2486. let result=[];
  2487. if (dayCount<=0) return result;
  2488. if (!Array.isArray(dayCount))
  2489. {
  2490. dayCount=parseInt(dayCount);
  2491. if (dayCount<=0) dayCount=1;
  2492. if (!data || !data.length) return result;
  2493. for(var i=0;i<data.length;++i)
  2494. {
  2495. result[i]=null;
  2496. if (this.IsNumber(data[i])) break;
  2497. }
  2498. var data=data.slice(0); //复制一份数据出来
  2499. for(var days=0;i<data.length;++i,++days)
  2500. {
  2501. if (days<dayCount-1)
  2502. {
  2503. result[i]=null;
  2504. continue;
  2505. }
  2506. let preValue=data[i-(dayCount-1)];
  2507. let sum=0;
  2508. for(let j=dayCount-1;j>=0;--j)
  2509. {
  2510. var value=data[i-j];
  2511. if (!this.IsNumber(value))
  2512. {
  2513. value=preValue; //空数据就取上一个数据
  2514. data[i-j]=value;
  2515. }
  2516. else
  2517. {
  2518. preValue=value;
  2519. }
  2520. sum+=value;
  2521. }
  2522. result[i]=sum/dayCount;
  2523. }
  2524. }
  2525. else
  2526. {
  2527. for(var i=0;i<data.length;++i)
  2528. {
  2529. result[i]=null;
  2530. if (i>=dayCount.length) continue;
  2531. var sumCount=dayCount[i];
  2532. if (!this.IsNumber(sumCount)) continue;
  2533. if (sumCount<=0) continue;
  2534. var sum=0;
  2535. var count=0;
  2536. for(var j=i, k=0;j>=0 && k<sumCount;--j,++k)
  2537. {
  2538. sum+=data[j];
  2539. ++count;
  2540. }
  2541. if (count>0) result[i]=sum/count;
  2542. }
  2543. }
  2544. return result;
  2545. }
  2546. //指数平均数指标 EMA(close,10)
  2547. //N 支持周期数组
  2548. this.EMA=function(data,dayCount)
  2549. {
  2550. var result = [];
  2551. if (data.length<=0) return result;
  2552. if (Array.isArray(dayCount))
  2553. {
  2554. for(var i=0;i<dayCount.length;++i)
  2555. {
  2556. var period=dayCount[i];
  2557. if (!this.IsNumber(period)) continue;
  2558. period=parseInt(period); //周期用整数
  2559. if (period<=0) continue;
  2560. if (period>i+1) period=i+1;
  2561. //EMA(N) = 2/(N+1)*C + (N-1)/(N+1)*EMA', EMA'为前一天的ema
  2562. var EMAFactor=[ 2/ (period + 1), (period - 1) / (period + 1)];
  2563. var ema=null;
  2564. var lastEMA=null;
  2565. for(var j=0;j<period;++j)
  2566. {
  2567. var index=i-(period-j-1);
  2568. var value=data[index];
  2569. if (!this.IsNumber(value)) coninue;
  2570. if (lastEMA==null)
  2571. {
  2572. ema=value; //第一个EMA为第一个数据的价格
  2573. lastEMA=ema;
  2574. }
  2575. else
  2576. {
  2577. ema = EMAFactor[0] * value + EMAFactor[1] * lastEMA;
  2578. lastEMA=ema;
  2579. }
  2580. }
  2581. result[i]=ema;
  2582. }
  2583. }
  2584. else
  2585. {
  2586. dayCount=parseInt(dayCount);
  2587. if (dayCount<=0) return result;
  2588. var offset=0;
  2589. //取首个有效数据
  2590. for(;offset<data.length;++offset)
  2591. {
  2592. if (data[offset]!=null && !isNaN(data[offset]))
  2593. break;
  2594. }
  2595. var p1Index=offset;
  2596. var p2Index=offset+1;
  2597. result[p1Index]=data[p1Index];
  2598. for(var i=offset+1;i<data.length;++i,++p1Index,++p2Index)
  2599. {
  2600. result[p2Index]=((2*data[p2Index]+(dayCount-1)*result[p1Index]))/(dayCount+1);
  2601. }
  2602. }
  2603. return result;
  2604. }
  2605. this.XMA = function (data, n)
  2606. {
  2607. var result = [];
  2608. var offset = 0;
  2609. for (; offset < data.length; ++offset)
  2610. {
  2611. if (this.IsNumber(data[offset])) break;
  2612. }
  2613. var p = parseInt((n - 2) / 2);
  2614. var sum = 0;
  2615. var count = 0, start = 0, end = 0;
  2616. for (var i = offset, j=0; i < data.length; ++i)
  2617. {
  2618. start = i - p - 1;
  2619. end = i + (n - p) - 1;
  2620. for (j = start; j < end; ++j)
  2621. {
  2622. if (j >= 0 && j < data.length)
  2623. {
  2624. if (this.IsNumber(data[j]))
  2625. {
  2626. sum += data[j];
  2627. ++count;
  2628. }
  2629. }
  2630. }
  2631. if (count != 0) result[i] = (sum / count);
  2632. else result[i] = null;
  2633. sum = 0;
  2634. count = 0;
  2635. }
  2636. return result;
  2637. }
  2638. /*
  2639. SMA 移动平均
  2640. 返回移动平均
  2641. 用法 SMA(XNM) X的M日移动平均M为权重如Y=(X*M+Y'*(N-M))/N
  2642. */
  2643. this.SMA=function(data,n,m)
  2644. {
  2645. var result = [];
  2646. if (Array.isArray(n))
  2647. {
  2648. for( var i=0;i<n.length;++i)
  2649. {
  2650. var period=n[i];
  2651. if (!this.IsNumber(period)) continue;
  2652. period=parseInt(period);
  2653. if (period<=0) continue;
  2654. if (period>i+1) period=i+1;
  2655. var lastSMA=null;
  2656. var sma=null;
  2657. for(var j=0;j<period;++j)
  2658. {
  2659. var index=i-(period-j-1);
  2660. var item=data[index];
  2661. if (!this.IsNumber(item)) continue;
  2662. if (lastSMA==null)
  2663. {
  2664. lastSMA=item;
  2665. sma=item;
  2666. }
  2667. else
  2668. {
  2669. sma=(m*item+(period-m)*lastSMA)/period;
  2670. lastSMA=sma;
  2671. }
  2672. }
  2673. result[i]=sma;
  2674. }
  2675. }
  2676. else
  2677. {
  2678. var i=n;
  2679. var lastData=null;
  2680. for(;i<data.length; ++i)
  2681. {
  2682. if (data[i]==null || isNaN(data[i])) continue;
  2683. lastData=data[i];
  2684. result[i]=lastData; //第一天的数据
  2685. break;
  2686. }
  2687. for(++i;i<data.length;++i)
  2688. {
  2689. result[i]=(m*data[i]+(n-m)*lastData)/n;
  2690. lastData=result[i];
  2691. }
  2692. }
  2693. return result;
  2694. }
  2695. /*
  2696. 求动态移动平均.
  2697. 用法: DMA(X,A),求X的动态移动平均.
  2698. 算法: 若Y=DMA(X,A) Y=A*X+(1-A)*Y',其中Y'表示上一周期Y值,A必须小于1.
  2699. 例如:DMA(CLOSE,VOL/CAPITAL)表示求以换手率作平滑因子的平均价
  2700. */
  2701. this.DMA=function(data,data2)
  2702. {
  2703. var result = [];
  2704. if (data.length<0 || data.length!=data2.length) return result;
  2705. var index=0;
  2706. for(;index<data.length;++index)
  2707. {
  2708. if (data[index]!=null && !isNaN(data[index]) && data2[index]!=null && !isNaN(data2[index]))
  2709. {
  2710. result[index]=data[index];
  2711. break;
  2712. }
  2713. }
  2714. for(index=index+1;index<data.length;++index)
  2715. {
  2716. if (data[index]==null || data2[index]==null)
  2717. result[index]=null;
  2718. else
  2719. {
  2720. if (data[index]<1)
  2721. result[index]=(data2[index]*data[index])+(1-data2[index])*result[index-1];
  2722. else
  2723. result[index]= data[index];
  2724. }
  2725. }
  2726. return result;
  2727. }
  2728. /*
  2729. 返回加权移动平均
  2730. 用法:WMA(X,N):X的N日加权移动平均.
  2731. 算法:Yn=(1*X1+2*X2+...+n*Xn)/(1+2+...+n)
  2732. */
  2733. this.WMA = function (data, dayCount)
  2734. {
  2735. let result = [];
  2736. if (!data || !data.length) return result;
  2737. if (dayCount < 1) dayCount = 1;
  2738. var i = 0;
  2739. for (i = 0; i < data.length && !this.IsNumber(data[i]); ++i)
  2740. {
  2741. result[i] = null;
  2742. }
  2743. var data = data.slice(0);
  2744. for (var days = 0; i < data.length; ++i, ++days)
  2745. {
  2746. if (days < dayCount - 1)
  2747. {
  2748. result[i] = null;
  2749. continue;
  2750. }
  2751. var preValue = data[i - (dayCount - 1)];
  2752. var sum = 0;
  2753. var count = 0;
  2754. for (var j = dayCount - 1; j >= 0; --j)
  2755. {
  2756. var value = data[i - j];
  2757. if (!this.IsNumber(value))
  2758. {
  2759. value = preValue;
  2760. data[i - j] = value;
  2761. }
  2762. else
  2763. preValue = value;
  2764. count += dayCount - j;
  2765. sum += value * (dayCount - j);
  2766. }
  2767. result[i] = sum / count;
  2768. }
  2769. return result;
  2770. }
  2771. /*
  2772. 返回平滑移动平均
  2773. 用法:MEMA(X,N):X的N日平滑移动平均,如Y=(X+Y'*(N-1))/N
  2774. MEMA(X,N)相当于SMA(X,N,1)
  2775. */
  2776. this.MEMA = function (data, dayCount)
  2777. {
  2778. let result = [];
  2779. if (!data || !data.length) return result;
  2780. var i = 0, j = 0;
  2781. for (j = 0; j < data.length && !this.IsNumber(data[j]); ++j)
  2782. {
  2783. result[j] = null;
  2784. }
  2785. i = j;
  2786. if (dayCount < 1 || i + dayCount >= data.length) return result;
  2787. var sum = 0;
  2788. var data = data.slice(0);
  2789. for (; i < j + dayCount; ++i)
  2790. {
  2791. result[i] = null;
  2792. if (!this.IsNumber(data[i]) && i - 1 >= 0)
  2793. data[i] = data[i - 1];
  2794. sum += data[i];
  2795. }
  2796. result[i - 1] = sum / dayCount;
  2797. for (; i < data.length; ++i)
  2798. {
  2799. if (this.IsNumber(result[i - 1]) && this.IsNumber(data[i]))
  2800. result[i] = (data[i] + result[i - 1] * (dayCount - 1)) / dayCount;
  2801. else if (i - 1 > -1 && this.IsNumber(result[i - 1]))
  2802. result[i] = result[i - 1];
  2803. else
  2804. result[i] = null;
  2805. }
  2806. return result;
  2807. }
  2808. /*
  2809. 加权移动平均
  2810. 返回加权移动平均
  2811. 用法:EXPMA(X,M):X的M日加权移动平均
  2812. EXPMA[i]=buffer[i]*para+(1-para)*EXPMA[i-1] para=2/(1+__para)
  2813. */
  2814. this.EXPMA=function(data,dayCount)
  2815. {
  2816. let result=[];
  2817. if (dayCount>=data.length) return result;
  2818. let i=dayCount;
  2819. for(;i<data.length;++i) //获取第1个有效数据
  2820. {
  2821. if (data[i]!=null)
  2822. {
  2823. result[i]=data[i];
  2824. break;
  2825. }
  2826. }
  2827. for (i=i+1; i < data.length; ++i)
  2828. {
  2829. if (result[i-1]!=null && data[i]!=null)
  2830. result[i]=(2*data[i]+(dayCount-1)*result[i-1])/(dayCount+1);
  2831. else if (result[i-1]!=null)
  2832. result[i]=result[i-1];
  2833. }
  2834. return result;
  2835. }
  2836. //加权平滑平均,MEMA[i]=SMA[i]*para+(1-para)*SMA[i-1] para=2/(1+__para)
  2837. this.EXPMEMA=function(data,dayCount)
  2838. {
  2839. var result=[];
  2840. if (dayCount>=data.length) return result;
  2841. var index=0;
  2842. for(;index<data.length;++index)
  2843. {
  2844. if (data[index] && !isNaN(data[index])) break;
  2845. }
  2846. var sum=0;
  2847. for(var i=0; index<data.length && i<dayCount;++i, ++index)
  2848. {
  2849. if (data[index] && !isNaN(data[index]))
  2850. sum+=data[index];
  2851. else
  2852. sum+=data[index-1];
  2853. }
  2854. result[index-1]=sum/dayCount;
  2855. for(;index<data.length;++index)
  2856. {
  2857. if(result[index-1]!=null && data[index]!=null)
  2858. result[index]=(2*data[index]+(dayCount-1)*result[index-1])/(dayCount+1);
  2859. else if(result[index-1]!=null)
  2860. result[index] = result[index-1];
  2861. }
  2862. return result;
  2863. }
  2864. /*
  2865. 向前累加到指定值到现在的周期数.
  2866. 用法:SUMBARS(X,A):将X向前累加直到大于等于A,返回这个区间的周期数
  2867. 例如:SUMBARS(VOL,CAPITAL)求完全换手到现在的周期数
  2868. */
  2869. this.SUMBARS = function (data, data2)
  2870. {
  2871. var result = [];
  2872. if (!data || !data.length || !data2 || !data2.length) return result;
  2873. var start = 0, i = 0, j = 0;
  2874. for (; start < data.length && !this.IsNumber(data[start]); ++start)
  2875. {
  2876. result[start] = null;
  2877. }
  2878. var total = 0;
  2879. for (i = data.length - 1; i >= start; --i)
  2880. {
  2881. for (j = i, total = 0; j >= start && total < data2[i]; --j)
  2882. total += data[j];
  2883. if (j < start) result[i] = null;
  2884. else result[i] = i - j;
  2885. }
  2886. for (i = start + 1; i < data.length; ++i)
  2887. {
  2888. if (result[i] == null)
  2889. result[i] = result[i - 1];
  2890. }
  2891. return result;
  2892. }
  2893. /*
  2894. 求相反数.
  2895. 用法:REVERSE(X)返回-X.
  2896. 例如:REVERSE(CLOSE)返回-CLOSE
  2897. */
  2898. this.REVERSE = function (data)
  2899. {
  2900. if (this.IsNumber(data))
  2901. {
  2902. return 0-data;
  2903. }
  2904. var result = [];
  2905. var i = 0;
  2906. for (; i < data.length && !this.IsNumber(data[i]); ++i)
  2907. {
  2908. result[i] = null;
  2909. }
  2910. for (; i < data.length; ++i)
  2911. {
  2912. if (!this.IsNumber(data[i]))
  2913. result[i] = null;
  2914. else
  2915. result[i] = 0 - data[i];
  2916. }
  2917. return result;
  2918. }
  2919. this.COUNT=function(data,n)
  2920. {
  2921. if (Array.isArray(n))
  2922. {
  2923. var start=null;
  2924. var dataCount=data.length;
  2925. for(var i=0;i<dataCount;++i)
  2926. {
  2927. if (this.IsNumber(data[i]))
  2928. {
  2929. start=i;
  2930. break;
  2931. }
  2932. }
  2933. if (start==null) return [];
  2934. var result=[];
  2935. var count=0;
  2936. for(var i=0;i<n.length;++i)
  2937. {
  2938. var period=n[i];
  2939. if (period==0)
  2940. {
  2941. result[i]=0;
  2942. continue;
  2943. }
  2944. if (!IFrameSplitOperator.IsNumber(period) ) period=i+1; //无效周期 第一个有效值开始.
  2945. else if (period<0) period=i+1;
  2946. count=0;
  2947. for(var j=i, k=0 ;j>=0 && k<period ;--j,++k) //当前往前period天 统计
  2948. {
  2949. if (data[j]) ++count;
  2950. }
  2951. result[i]=count;
  2952. }
  2953. return result;
  2954. }
  2955. else
  2956. {
  2957. var period=n;
  2958. var dataCount=data.length;
  2959. var period=period<1?dataCount:period;
  2960. var i=0,j=0;
  2961. for(;i<dataCount;++i) // 取第1个有效数据
  2962. {
  2963. if (this.IsNumber(data[i])) break;
  2964. }
  2965. var result=[];
  2966. var days=0;
  2967. for(;i<dataCount && j<period; ++i,++j)
  2968. {
  2969. days=data[i]?days+1:days;
  2970. result[i]=days;
  2971. }
  2972. for(;i<dataCount;++i)
  2973. {
  2974. if (data[i-period] && days) days--;
  2975. days=data[i] ? days+1 : days;
  2976. result[i]=days;
  2977. }
  2978. return result;
  2979. }
  2980. }
  2981. /*
  2982. HHV 最高值
  2983. 求最高值
  2984. 用法 HHV(XN) 求N周期内X最高值N=0则从第一个有效值开始
  2985. 例如 HHV(HIGH,30) 表示求30日最高价
  2986. */
  2987. this.HHV=function(data,n)
  2988. {
  2989. let result = [];
  2990. if (Array.isArray(n))
  2991. {
  2992. var max = null;
  2993. for (var i = 0, j = 0; i < data.length; ++i)
  2994. {
  2995. result[i] = null;
  2996. if (i >= n.length) continue;
  2997. max = null;
  2998. var count = n[i];
  2999. if (count > 0 && count <= i)
  3000. {
  3001. for (j = i - count; j <= i; ++j)
  3002. {
  3003. if (max == null || max < data[j]) max = data[j];
  3004. }
  3005. }
  3006. else
  3007. {
  3008. count = i;
  3009. for (j = 0; j <= i; ++j)
  3010. {
  3011. if (max == null || max < data[j]) max = data[j];
  3012. }
  3013. }
  3014. result[i] = max;
  3015. }
  3016. }
  3017. else
  3018. {
  3019. if (!IFrameSplitOperator.IsNonEmptyArray(data)) return result;
  3020. n=parseInt(n);
  3021. if (n<=0) n=data.length;
  3022. else if (n>data.length) n=data.length;
  3023. var nStart=this.GetFirstVaildIndex(data);
  3024. if (nStart>=data.length) return result;
  3025. var nMax = nStart;
  3026. if (nMax < data.length) result[nMax] = data[nMax];
  3027. for (var i = nMax + 1, j = 2; i < data.length && j < n; ++i, ++j)
  3028. {
  3029. if (data[i] >= data[nMax]) nMax = i;
  3030. result[i] = data[nMax];
  3031. }
  3032. for (; i < data.length; ++i)
  3033. {
  3034. if (i - nMax < n)
  3035. {
  3036. nMax = data[i] < data[nMax] ? nMax : i;
  3037. }
  3038. else
  3039. {
  3040. for (j = nMax = (i - n + 1); j <= i; ++j)
  3041. {
  3042. nMax = data[j] < data[nMax] ? nMax : j;
  3043. }
  3044. }
  3045. result[i] = data[nMax];
  3046. }
  3047. }
  3048. return result;
  3049. }
  3050. /*
  3051. HV(X,N)求X在N个周期内不包含当前k线的最高值
  3052. 1若N为0则从第一个有效值开始算起(不包含当前K线)
  3053. 2当N为有效值但当前的k线数不足N根按照实际的根数计算第一根k线返回空值
  3054. 3N为空值时返回空值
  3055. 4N可以是变量
  3056. 例1
  3057. HH:HV(H,10);//求前10根k线的最高点。
  3058. 例2
  3059. N:=BARSLAST(DATE<>REF(DATE,1))+1;
  3060. ZH:VALUEWHEN(DATE<>REF(DATE,1),HV(H,N));//在分钟周期上,求昨天最高价。
  3061. 例3
  3062. HV(H,5) REF(HHV(H,5),1) 的结果是一样的用HV编写更加方便
  3063. */
  3064. this.HV=function(data,n)
  3065. {
  3066. var result=this.HHV(data,n);
  3067. return this.REF(result,1);
  3068. }
  3069. /*
  3070. LLV 最低值
  3071. 求最低值
  3072. 用法 LLV(XN) 求N周期内X最低值N=0则从第一个有效值开始
  3073. 例如 LLV(LOW0) 表示求历史最低价
  3074. */
  3075. this.LLV=function(data,n)
  3076. {
  3077. var result = [];
  3078. if (Array.isArray(n))
  3079. {
  3080. for (var i = 0; i < data.length; ++i)
  3081. {
  3082. result[i] = null;
  3083. if (i >= n.length) continue;
  3084. var min = null;
  3085. var count = n[i];
  3086. if (count > 0 && count <= i)
  3087. {
  3088. for (var j = i - count; j <= i; ++j)
  3089. {
  3090. if (min == null || min > data[j]) min = data[j];
  3091. }
  3092. }
  3093. else
  3094. {
  3095. count = i;
  3096. for (var j = 0; j <= i; ++j)
  3097. {
  3098. if (min == null || min > data[j]) min = data[j];
  3099. }
  3100. }
  3101. result[i] = min;
  3102. }
  3103. }
  3104. else
  3105. {
  3106. if (!IFrameSplitOperator.IsNonEmptyArray(data)) return result;
  3107. n=parseInt(n);
  3108. if (n<=0) n=data.length;
  3109. else if (n>data.length) n=data.length;
  3110. var nStart=this.GetFirstVaildIndex(data);
  3111. if (nStart>=data.length) return result;
  3112. var nMin=nStart;
  3113. if (nMin<data.length) result[nMin]=data[nMin];
  3114. for(var i=nMin+1,j=2;i<data.length && j<n;++i,++j)
  3115. {
  3116. if (data[i]<=data[nMin]) nMin=i;
  3117. result[i]=data[nMin];
  3118. }
  3119. for(;i<data.length;++i)
  3120. {
  3121. if (i-nMin<n)
  3122. {
  3123. nMin=data[i]>data[nMin]?nMin:i;
  3124. }
  3125. else
  3126. {
  3127. for(j=nMin=(i-n+1);j<=i;++j)
  3128. {
  3129. nMin=data[j]>data[nMin]?nMin:j;
  3130. }
  3131. }
  3132. result[i]=data[nMin];
  3133. }
  3134. }
  3135. return result;
  3136. }
  3137. /*
  3138. LV(X,N) 求X在N个周期内的最小值不包含当前k线
  3139. 1若N为0则从第一个有效值开始算起;
  3140. 2当N为有效值但当前的k线数不足N根按照实际的根数计算;
  3141. 3N为空值时返回空值
  3142. 4N可以是变量
  3143. 例1
  3144. LL:LV(L,10);//求前面10根k线的最低点。(不包含当前k线)
  3145. 例2
  3146. N:=BARSLAST(DATE<>REF(DATE,1))+1;//分钟周期,日内k线根数
  3147. ZL:VALUEWHEN(DATE<>REF(DATE,1),LV(L,N));//在分钟周期上,求昨天最低价。
  3148. 例3
  3149. LV(L,5) REF(LLV(L,5),1) 的结果是一样的用LV编写更加方便
  3150. */
  3151. this.LV=function(data,n)
  3152. {
  3153. var result=this.LLV(data,n);
  3154. return this.REF(result,1);
  3155. }
  3156. this.STD=function(data,n)
  3157. {
  3158. var result=[];
  3159. var nStart=this.GetFirstVaildIndex(data);
  3160. if (!IFrameSplitOperator.IsNumber(n)) return result;
  3161. if(nStart+n>data.length || n<1) return result;
  3162. var i=nStart, j=0, bFirst=true, dTotal=0, dAvg=0;
  3163. for(i+=n-1;i<data.length;++i)
  3164. {
  3165. dTotal = 0;
  3166. if(bFirst)
  3167. {
  3168. bFirst = false;
  3169. for(j=i-n+1;j<=i;++j)
  3170. {
  3171. dAvg += data[j];
  3172. }
  3173. dAvg /= n;
  3174. }
  3175. else
  3176. {
  3177. dAvg += (data[i]-data[i-n])/n;
  3178. }
  3179. for(j=i-n+1;j<=i;++j)
  3180. {
  3181. dTotal += (data[j]-dAvg)*(data[j]-dAvg);
  3182. }
  3183. result[i] = Math.sqrt(dTotal/(n-1));
  3184. }
  3185. return result;
  3186. }
  3187. //STDDEV(X,N) 返回标准偏差
  3188. //将标准差除以样本大小N的平方根即可得出标准误差。标准误差 = σ/sqrt(n)
  3189. this.STDDEV=function(data,n)
  3190. {
  3191. var result=[];
  3192. if (!Array.isArray(data)) return result;
  3193. var nStart=this.GetFirstVaildIndex(data);
  3194. if (!IFrameSplitOperator.IsNumber(n)) return result;
  3195. if(nStart+n>data.length || n<1) return result;
  3196. var i=nStart, j=0, bFirst=true, dTotal=0, dAvg=0;
  3197. for(i+=n-1;i<data.length;++i)
  3198. {
  3199. dTotal = 0;
  3200. if(bFirst)
  3201. {
  3202. bFirst = false;
  3203. for(j=i-n+1;j<=i;++j)
  3204. {
  3205. dAvg += data[j];
  3206. }
  3207. dAvg /= n;
  3208. }
  3209. else
  3210. {
  3211. dAvg += (data[i]-data[i-n])/n;
  3212. }
  3213. for(j=i-n+1;j<=i;++j)
  3214. {
  3215. dTotal += (data[j]-dAvg)*(data[j]-dAvg);
  3216. }
  3217. result[i] = Math.sqrt(dTotal/(n-1))/Math.sqrt(n);
  3218. }
  3219. return result;
  3220. }
  3221. //平均绝对方差
  3222. this.AVEDEV=function(data,n)
  3223. {
  3224. var result=[];
  3225. var total=0;
  3226. var averageData=[]; //平均值
  3227. for(var i=n-1;i<data.length;++i)
  3228. {
  3229. total=0;
  3230. for(var j=0;j<n;++j)
  3231. {
  3232. total+=data[i-j];
  3233. }
  3234. averageData[i]=total/n;
  3235. }
  3236. for(var i=n-1;i<data.length;++i)
  3237. {
  3238. total=0;
  3239. for(var j=0;j<n;++j)
  3240. {
  3241. total+=Math.abs(data[i-j]-averageData[i]);
  3242. }
  3243. result[i]=total/n;
  3244. }
  3245. return result;
  3246. }
  3247. //上穿
  3248. this.CROSS=function(data,data2)
  3249. {
  3250. var result = [];
  3251. if (Array.isArray(data) && Array.isArray(data2))
  3252. {
  3253. if (data.length != data2.length) return result = [];
  3254. var index = 0;
  3255. for (; index < data.length; ++index)
  3256. {
  3257. if (this.IsNumber(data[index]) && this.IsNumber(data2[index]))
  3258. break;
  3259. }
  3260. for (++index; index < data.length; ++index)
  3261. {
  3262. result[index] = (data[index] > data2[index] && data[index - 1] < data2[index - 1]) ? 1 : 0;
  3263. }
  3264. }
  3265. else if (Array.isArray(data) && typeof (data2) == 'number')
  3266. {
  3267. var index = 0;
  3268. for (; index < data.length; ++index)
  3269. {
  3270. if (this.IsNumber(data[index])) break;
  3271. }
  3272. for (++index; index < data.length; ++index)
  3273. {
  3274. result[index] = (data[index] > data2 && data[index - 1] < data2) ? 1 : 0;
  3275. }
  3276. }
  3277. else if (typeof (data) == 'number' && Array.isArray(data2))
  3278. {
  3279. var index = 0;
  3280. for (; index < data2.length; ++index)
  3281. {
  3282. if (this.IsNumber(data2[index])) break;
  3283. }
  3284. for (++index; index < data2.length; ++index)
  3285. {
  3286. result[index] = (data2[index] < data && data2[index - 1] > data) ? 1 : 0;
  3287. }
  3288. }
  3289. return result;
  3290. }
  3291. /*
  3292. CROSSDOWN(A,B)表示当A从上方向下穿B成立返回1(Yes)否则返回0(No)
  3293. 1CROSSDOWN(A,B)等同于CROSS(B,A)CROSSDOWN(A,B)编写更利于理解
  3294. 例1
  3295. MA5:=MA(C,5);
  3296. MA10:=MA(C,10);
  3297. CROSSDOWN(MA5,MA10)//MA5下穿MA10
  3298. */
  3299. this.CROSSDOWN=function(data,data2)
  3300. {
  3301. return this.CROSS(data2,data);
  3302. }
  3303. //累乘
  3304. this.MULAR=function(data,n)
  3305. {
  3306. var result=[];
  3307. if(data.length<n) return result;
  3308. var index=n;
  3309. for(;index<data.length;++index)
  3310. {
  3311. if (data[index]!=null && !isNaN(data[index]))
  3312. {
  3313. result[index]=data[index];
  3314. break;
  3315. }
  3316. }
  3317. for(++index;index<data.length;++index)
  3318. {
  3319. result[index]=result[index-1]*data[index];
  3320. }
  3321. return result;
  3322. }
  3323. this.SUM=function(data,n)
  3324. {
  3325. var result=[];
  3326. if (!Array.isArray(n))
  3327. {
  3328. if (n==0)
  3329. {
  3330. var start=-1;
  3331. for(var i=0; i<data.length; ++i) //取第1个有效数
  3332. {
  3333. if (IFrameSplitOperator.IsNumber(data[i]))
  3334. {
  3335. start=i;
  3336. break;
  3337. }
  3338. }
  3339. if (start<0) return result;
  3340. result[start]=data[start];
  3341. for (var i=start+1; i<data.length; ++i)
  3342. {
  3343. result[i] = result[i-1]+data[i];
  3344. }
  3345. }
  3346. else
  3347. {
  3348. result[0]=data[0];
  3349. for(var i=1;i<n && i<data.length;++i) //前面小于N周期的累加
  3350. {
  3351. result[i] = result[i-1]+data[i];
  3352. }
  3353. for(var i=n-1,j=0;i<data.length;++i,++j)
  3354. {
  3355. for(var k=0;k<n;++k)
  3356. {
  3357. if (k==0) result[i]=data[k+j];
  3358. else result[i]+=data[k+j];
  3359. }
  3360. }
  3361. }
  3362. }
  3363. else
  3364. {
  3365. for(var i=0;i<data.length;++i)
  3366. {
  3367. result[i]=null;
  3368. var totalCount=n[i];
  3369. if (!(totalCount>0)) continue;
  3370. for(var j=i, k=0 ;j>=0 && k<totalCount ;--j,++k)
  3371. {
  3372. if (k==0) result[i]=data[j];
  3373. else result[i]+=data[j];
  3374. }
  3375. }
  3376. }
  3377. return result;
  3378. }
  3379. /*
  3380. BARSCOUNT 有效数据周期数
  3381. 求总的周期数
  3382. 用法 BARSCOUNT(X) 第一个有效数据到当前的天数
  3383. 例如 BARSCOUNT(CLOSE) 对于日线数据取得上市以来总交易日数对于分笔成交取得当日成交笔数对于1分钟线取得当日交易分钟数
  3384. */
  3385. this.BARSCOUNT=function(data)
  3386. {
  3387. let result=[];
  3388. let days=null;
  3389. for(let i in data)
  3390. {
  3391. result[i]=0;
  3392. if (days==null)
  3393. {
  3394. if (!this.IsNumber(data[i])) contnue;
  3395. days=0;
  3396. }
  3397. result[i]=days;
  3398. ++days;
  3399. }
  3400. return result;
  3401. }
  3402. //DEVSQ 数据偏差平方和
  3403. //DEVSQ(X,N)  返回数据偏差平方和。
  3404. this.DEVSQ=function(data,n)
  3405. {
  3406. if (this.IsNumber(data) && this.IsNumber(n))
  3407. return 0;
  3408. var result=[];
  3409. if (Array.isArray(data))
  3410. {
  3411. var num = null;
  3412. if (Array.isArray(n)) //取最后一个有效数
  3413. {
  3414. for(var i=n.length-1;i>=0;--i)
  3415. {
  3416. if (this.IsNumber(n[i]))
  3417. {
  3418. num = parseInt(n[i]);
  3419. break;
  3420. }
  3421. }
  3422. }
  3423. else
  3424. {
  3425. num = parseInt(n);
  3426. }
  3427. if (!this.IsNumber(num)) return result;
  3428. var datanum = data.length;
  3429. var i = 0, j = 0, k = 0;
  3430. var E = 0, DEV = 0;
  3431. for(i = 0; i < datanum && !this.IsNumber(data[i]); ++i)
  3432. {
  3433. result[i] = null;
  3434. }
  3435. if (num < 1 || i+num>datanum) return result;
  3436. for(E=0; i < datanum && j < num; ++i,++j)
  3437. E += data[i]/num;
  3438. if (j == num)
  3439. {
  3440. DEV = 0;
  3441. for(i--; k < num; k++)
  3442. DEV += (data[i-k]-E) * (data[i-k]-E);
  3443. result[i] = DEV;
  3444. i++;
  3445. }
  3446. for(; i < datanum; ++i)
  3447. {
  3448. E += (data[i] - data[i-num]) / num;
  3449. for(DEV=0, k = 0; k < num; ++k)
  3450. DEV += (data[i-k]-E) * (data[i-k]-E);
  3451. result[i] = DEV;
  3452. }
  3453. }
  3454. return result;
  3455. }
  3456. //NOT 取反
  3457. //求逻辑非。
  3458. //用法: NOT(X) 返回非X,即当X=0时返回1,否则返回0。
  3459. //例如: NOT(ISUP) 表示平盘或收阴。
  3460. this.NOT=function(data)
  3461. {
  3462. let isNumber=typeof(data)=='number';
  3463. if (isNumber) return data? 0:1;
  3464. let result=[];
  3465. for(let i in data)
  3466. {
  3467. result[i]=null;
  3468. if (this.IsNumber(data[i])) result[i]=data[i]?0:1;
  3469. }
  3470. return result;
  3471. }
  3472. //FORCAST 线性回归预测值
  3473. //FORCAST(X,N)  返回线性回归预测值。
  3474. this.FORCAST=function(data,n)
  3475. {
  3476. var result=[];
  3477. if (typeof(n)!='number') n=parseInt(n); //字符串的转成数值型
  3478. var num = n;
  3479. var datanum = data.length;
  3480. if (num < 1 || num >= datanum)
  3481. return result;
  3482. var Ex = 0, Ey = 0, Sxy = 0, Sxx = 0, Const, Slope;
  3483. var i, j,x;
  3484. for(j = 0; j < datanum && !this.IsNumber(data[j]); ++j)
  3485. {
  3486. result[j] = null;
  3487. }
  3488. for(i = j+num-1; i < datanum; ++i)
  3489. {
  3490. Ex = Ey = Sxy = Sxx = 0;
  3491. for (j = 0, x = num; j < num && j <= i; ++j,--x)
  3492. {
  3493. Ex +=x;
  3494. Ey += data[i - j];
  3495. }
  3496. Ex /= num;
  3497. Ey /= num;
  3498. for (j = 0, x = num; j < num && j <= i; ++j, --x)
  3499. {
  3500. Sxy += (x-Ex)*(data[i-j]-Ey);
  3501. Sxx += (x-Ex)*(x-Ex);
  3502. }
  3503. Slope = Sxy / Sxx;
  3504. Const = Ey - Ex*Slope;
  3505. result[i] = Slope * num + Const;
  3506. }
  3507. return result;
  3508. }
  3509. //SLOPE 线性回归斜率
  3510. //SLOPE(X,N)  返回线性回归斜率。
  3511. this.SLOPE=function(data,n)
  3512. {
  3513. let result=[];
  3514. if (typeof(n)!='number') n=parseInt(n); //字符串的转成数值型
  3515. if (n<1 || !data.length) return result;
  3516. if (n>=data.length) return result;
  3517. let start=0;
  3518. for(let i=0;i<data.length;++i,++start)
  3519. {
  3520. result[i]=null;
  3521. if (this.IsNumber(data[i])) break;
  3522. }
  3523. let x,y,xy,xx;
  3524. for(let i=start+n-1;i<data.length;++i)
  3525. {
  3526. result[i]=null;
  3527. x=y=xy=xx=0;
  3528. for(var j=0;j<n && j<=i; ++j)
  3529. {
  3530. x+=(i-j); //数据索引相加
  3531. y+=data[i-j]; //数据相加
  3532. }
  3533. x=x/n; y=y/n;
  3534. for(j=0;j<n && j<=i; ++j)
  3535. {
  3536. xy+=(i-j-x)*(data[i-j]-y);
  3537. xx+=(i-j-x)*(i-j-x);
  3538. }
  3539. if (xx) result[i]= xy/xx;
  3540. else if (i) result[i]=result[i-1];
  3541. }
  3542. return result;
  3543. }
  3544. //STDP 总体标准差
  3545. //STDP(X,N)  返回总体标准差。
  3546. this.STDP=function(data,n)
  3547. {
  3548. var result=[];
  3549. var nStart=this.GetFirstVaildIndex(data);
  3550. if (!IFrameSplitOperator.IsNumber(n)) return result;
  3551. if(nStart+n>data.length || n<1) return result;
  3552. var i=nStart, j=0, bFirst=true, dTotal=0, dAvg=0;
  3553. for(i+=n-1;i<data.length;++i)
  3554. {
  3555. dTotal = 0;
  3556. if(bFirst)
  3557. {
  3558. bFirst = false;
  3559. for(j=i-n+1;j<=i;++j)
  3560. {
  3561. dAvg += data[j];
  3562. }
  3563. dAvg /= n;
  3564. }
  3565. else
  3566. {
  3567. dAvg += (data[i]-data[i-n])/n;
  3568. }
  3569. for(j=i-n+1;j<=i;++j)
  3570. {
  3571. dTotal += (data[j]-dAvg)*(data[j]-dAvg);
  3572. }
  3573. result[i] = Math.sqrt(dTotal/n);
  3574. }
  3575. return result;
  3576. }
  3577. //VAR 估算样本方差
  3578. //VAR(X,N)  返回估算样本方差。
  3579. this.VAR=function(data,n)
  3580. {
  3581. if (this.IsNumber(data) && this.IsNumber(n)) return 0;
  3582. var result=[];
  3583. if (Array.isArray(data) && this.IsNumber(n))
  3584. {
  3585. var num = parseInt(n);
  3586. var datanum = data.length;
  3587. if (num <= 0 || num >= datanum) return result;
  3588. var i, j;
  3589. for(i = 0; i < datanum && !this.IsNumber(data[i]); ++i)
  3590. {
  3591. result[i] = null;
  3592. }
  3593. var SigmaPowerX, SigmaX;
  3594. for (j = 0, i = i+num-1; i < datanum; ++i)
  3595. {
  3596. SigmaPowerX = SigmaX = 0;
  3597. for(j=0; j < num && j <= i; ++j)
  3598. {
  3599. SigmaPowerX += data[i-j] * data[i-j];
  3600. SigmaX += data[i-j];
  3601. }
  3602. result[i] = (num*SigmaPowerX - SigmaX*SigmaX) / num * (num -1);
  3603. }
  3604. }
  3605. else if (Array.isArray(data) && Array.isArray(n))
  3606. {
  3607. var start=this.GetFirstVaildIndex(data);
  3608. for(var i=start; i<data.length; ++i)
  3609. {
  3610. var SigmaPowerX = SigmaX = 0;
  3611. if (!this.IsNumber(n[i])) continue;
  3612. var num=parseInt(n[i]);
  3613. if (num <= 0 || i-(num-1)<0) continue;
  3614. for (var j = 0; j<num; ++j)
  3615. {
  3616. SigmaPowerX += data[i-j] * data[i-j];
  3617. SigmaX += data[i-j];
  3618. }
  3619. result[i] = (num*SigmaPowerX - SigmaX*SigmaX) / num * (num -1);
  3620. }
  3621. }
  3622. return result;
  3623. }
  3624. //VARP 总体样本方差
  3625. //VARP(X,N)  返回总体样本方差 。
  3626. this.VARP=function(data,n)
  3627. {
  3628. var result=[];
  3629. if (typeof(n)!='number') n=parseInt(n); //字符串的转成数值型
  3630. var num = n;
  3631. var datanum = data.length;
  3632. if (num < 1 || num >= datanum)
  3633. return result;
  3634. var i = 0, j = 0;
  3635. for (i = 0; i < datanum && !this.IsNumber(data[i]); ++i)
  3636. {
  3637. result[i] = null;
  3638. }
  3639. var SigmaPowerX = 0, SigmaX = 0;
  3640. for (; i < datanum && j < num; ++i, ++j)
  3641. {
  3642. SigmaPowerX += data[i] * data[i];
  3643. SigmaX += data[i];
  3644. }
  3645. if (j == num)
  3646. result[i-1] = (num*SigmaPowerX - SigmaX*SigmaX) / (num*num);
  3647. for(; i < datanum; ++i)
  3648. {
  3649. SigmaPowerX += data[i]*data[i] - data[i-num]*data[i-num];
  3650. SigmaX += data[i] - data[i-num];
  3651. result[i] = (num*SigmaPowerX - SigmaX*SigmaX) / (num*num);
  3652. }
  3653. return result;
  3654. }
  3655. //RANGE(A,B,C)表示A>B AND A<C;
  3656. this.RANGE=function(data,range,range2)
  3657. {
  3658. let isNumber=typeof(data)=='number';
  3659. let isNumber2=typeof(range)=='number';
  3660. let isNumber3=typeof(range2)=='number';
  3661. if (isNumber && isNumber2 && isNumber3)
  3662. {
  3663. if (data>Math.min(range,range2) && data<Math.max(range,range2)) return 1;
  3664. else return 0;
  3665. }
  3666. let result=[];
  3667. let value, rangeValue,rangValue2;
  3668. for(let i=0; i<data.length; ++i)
  3669. {
  3670. result[i]=null;
  3671. value=data[i];
  3672. if (!this.IsNumber(value)) continue;
  3673. if (!isNumber2)
  3674. {
  3675. if (i>=range.length) continue;
  3676. rangeValue=range[i];
  3677. }
  3678. else
  3679. {
  3680. rangeValue=range;
  3681. }
  3682. if (!this.IsNumber(rangeValue)) continue;
  3683. if (!isNumber3)
  3684. {
  3685. if (i>=range2.length) continue;
  3686. rangeValue2=range2[i];
  3687. }
  3688. else
  3689. {
  3690. rangeValue2=range2;
  3691. }
  3692. if (!this.IsNumber(rangeValue2)) continue;
  3693. result[i]= (value>Math.min(rangeValue,rangeValue2) && value<Math.max(rangeValue,rangeValue2)) ? 1:0;
  3694. }
  3695. return result;
  3696. }
  3697. this.EXIST=function(data,n)
  3698. {
  3699. n=parseInt(n);
  3700. if (typeof(data)=='number') return 0;
  3701. var latestID; //最新满足条件的数据索引
  3702. var result=[];
  3703. var value;
  3704. for(let i=0;i<data.length;++i)
  3705. {
  3706. result[i]=null;
  3707. value=data[i];
  3708. if (this.IsNumber(value) && value>0) latestID==i;
  3709. if (i-latestID<n) result[i]=1;
  3710. else result[i]=0;
  3711. }
  3712. return result;
  3713. }
  3714. //用法:BETWEEN(A,B,C)表示A处于B和C之间时返回1,否则返回0
  3715. //例如:BETWEEN(CLOSE,MA(CLOSE,20),MA(CLOSE,10))表示收盘价介于10日均线和20日均线之间
  3716. this.BETWEEN=function(condition, data, data2)
  3717. {
  3718. var result=[];
  3719. var isNumber=typeof(condition)=='number';
  3720. var isNumber2=typeof(data)=='number';
  3721. var isNumber3=typeof(data2)=='number';
  3722. if (isNumber && isNumber2 && isNumber3) //单数值
  3723. {
  3724. return (condition>=data && condition<=data2) ? 1 : 0;
  3725. }
  3726. for(var i in condition)
  3727. {
  3728. result[i]=0;
  3729. var item=condition[i];
  3730. var left=null, right=null;
  3731. if (isNumber2) left=data;
  3732. else if (i<data.length-1) left=data[i];
  3733. if (isNumber3) right=data2;
  3734. else if (i<data2.length-1) right=data2[i];
  3735. if (left==null || right==null) continue;
  3736. if (left>right)
  3737. {
  3738. if (item>=right && item<=left)
  3739. result[i]=1;
  3740. }
  3741. else
  3742. {
  3743. if (item<=right && item>=left)
  3744. result[i]=1;
  3745. }
  3746. }
  3747. return result;
  3748. }
  3749. /*
  3750. 过滤连续出现的信号.
  3751. 用法:TFILTER(买入条件,卖出条件,N);过滤掉买入(卖出)信号发出后,下一个反向信号发出前的所有买入(卖出)信号.
  3752. N=1表示仅对买入信号过滤;
  3753. N=2表示仅对卖出信号过滤;
  3754. N=0表示对买入和卖出信号都过滤,返回1,2表示买入或卖出条件成立;
  3755. 同一K线上只能有一个信号;
  3756. 例如:
  3757. ENTERLONG:TFILTER(买入,卖出,1);
  3758. EXITLONG:TFILTER(买入,卖出,2);
  3759. TFILTER(D,K,1) 等价于 D AND COUNT(D, BARSLAST(K)) == 1
  3760. TFILTER(D,K,2) 等价于 K AND COUNT(K, BARSLAST(D)) == 1
  3761. TFILTER(D,K,0) 需要做个判断如果满足 D AND COUNT(D, BARSLAST(K)) == 1 则返回1如果满足 K AND COUNT(K, BARSLAST(D)) == 1 则返回2
  3762. */
  3763. this.TFILTER=function(data,data2,n)
  3764. {
  3765. if (!this.IsNumber(n)) return [];
  3766. if (n==1)
  3767. {
  3768. return this.And(data,this.EQ(this.COUNT(data,this.BARSLAST(data2)),1));
  3769. }
  3770. else if (n==2)
  3771. {
  3772. return this.And(data2,this.EQ(this.COUNT(data2,this.BARSLAST(data)),1));
  3773. }
  3774. else if (n==0)
  3775. {
  3776. var result=this.And(data2,this.EQ(this.COUNT(data2,this.BARSLAST(data)),1));
  3777. var value=this.And(data2,this.EQ(this.COUNT(data2,this.BARSLAST(data)),1));
  3778. for(var i=0; i<result.length; ++i)
  3779. {
  3780. var item=value[i];
  3781. if (item>0) result[i]=2;
  3782. }
  3783. return result;
  3784. }
  3785. return [];
  3786. }
  3787. /*
  3788. 过滤连续出现的信号.
  3789. 用法:FILTER(X,N):X满足条件后,将其后N周期内的数据置为0,N为常量.
  3790. 例如:
  3791. FILTER(CLOSE>OPEN,5)查找阳线,5天内再次出现的阳线不被记录在内
  3792. */
  3793. this.FILTER = function (data, n)
  3794. {
  3795. var result = [];
  3796. for (let i = 0, j = 0; i < data.length; ++i)
  3797. {
  3798. if (data[i])
  3799. {
  3800. result[i] = 1;
  3801. for (j = 0; j < n && j + i + 1 < data.length; ++j)
  3802. {
  3803. result[j + i + 1] = 0;
  3804. }
  3805. i += n;
  3806. }
  3807. else
  3808. {
  3809. result[i] = 0;
  3810. }
  3811. }
  3812. return result;
  3813. }
  3814. this.BARSLAST=function(data)
  3815. {
  3816. var result=[];
  3817. if (!data) return result;
  3818. let day=null;
  3819. for(let i=0;i<data.length;++i)
  3820. {
  3821. result[i]=null;
  3822. if (data[i]>0) day=0;
  3823. else if (day!=null) ++day;
  3824. if (day!=null) result[i]=day;
  3825. }
  3826. return result;
  3827. }
  3828. /*
  3829. N周期内第一个条件成立到当前的周期数.
  3830. 用法:
  3831. BARSSINCEN(X,N):N周期内第一次X不为0到现在的天数,N为常量
  3832. 例如:
  3833. BARSSINCEN(HIGH>10,10)表示10个周期内股价超过10元时到当前的周期数
  3834. */
  3835. this.BARSSINCEN = function (data, n)
  3836. {
  3837. var result=[];
  3838. if (this.IsNumber(n) && Array.isArray(data))
  3839. {
  3840. var nPeriod=n;
  3841. if (nPeriod<1) nPeriod=data.length;
  3842. var i=this.GetFirstVaildIndex(data);
  3843. if (i>=data.length) return result;
  3844. var j=0;
  3845. if (i <= nPeriod - 1) j = nPeriod - 1;
  3846. else j = i;
  3847. result[j] = j - i;
  3848. for (; j < data.length; ++j)
  3849. {
  3850. if (this.IsNumber(result[j - 1]))
  3851. {
  3852. if (result[j - 1] + 1 < nPeriod)
  3853. {
  3854. result[j] = result[j - 1] + 1;
  3855. }
  3856. else
  3857. {
  3858. for (var k = j - nPeriod+1; k <= j; ++k)
  3859. {
  3860. if (!(Math.abs(data[k]) < 0.000001))
  3861. {
  3862. result[j] = j - k;
  3863. break;
  3864. }
  3865. }
  3866. }
  3867. }
  3868. else
  3869. {
  3870. if (!(Math.abs(data[j]) < 0.000001))
  3871. result[j] = 0;
  3872. }
  3873. }
  3874. }
  3875. return result;
  3876. }
  3877. /*
  3878. 第一个条件成立到当前的周期数.
  3879. 用法:
  3880. BARSSINCE(X):第一次X不为0到现在的天数
  3881. 例如:
  3882. BARSSINCE(HIGH>10)表示股价超过10元时到当前的周期数
  3883. */
  3884. this.BARSSINCE = function (data)
  3885. {
  3886. var result = [];
  3887. var day = null;
  3888. for (let i = 0; i < data.length; ++i)
  3889. {
  3890. result[i] = null;
  3891. if (day == null)
  3892. {
  3893. if (data[i]) day = 0;
  3894. }
  3895. else
  3896. {
  3897. ++day;
  3898. }
  3899. if (day) result[i] = day;
  3900. }
  3901. return result;
  3902. }
  3903. /* func
  3904. 反正切值. 用法: ATAN(X)返回X的反正切值
  3905. 余弦值. 用法: COS(X)返回X的余弦值
  3906. 正弦值. 用法: SIN(X)返回X的正弦值
  3907. 正切值. 用法: TAN(X)返回X的正切值
  3908. 求自然对数. 用法: LN(X)以e为底的对数 例如: LN(CLOSE)求收盘价的对数
  3909. 求10为底的对数. 用法: LOG(X)取得X的对数 例如: LOG(100)等于2
  3910. 指数. 用法: EXP(X)为e的X次幂 例如: EXP(CLOSE)返回e的CLOSE次幂
  3911. 开平方. 用法: SQRT(X)为X的平方根 例如: SQRT(CLOSE)收盘价的平方根
  3912. */
  3913. this.Trigonometric = function (data, func)
  3914. {
  3915. if (!Array.isArray(data))
  3916. {
  3917. if (this.IsNumber(data)) return func(data);
  3918. return null;
  3919. }
  3920. else
  3921. {
  3922. var result = [];
  3923. for (let i in data)
  3924. {
  3925. var item = data[i];
  3926. if (this.IsNumber(item)) result[i] = func(item);
  3927. else result[i] = null;
  3928. }
  3929. return result;
  3930. }
  3931. }
  3932. //反正弦值. 用法: ASIN(X)返回X的反正弦值
  3933. this.ASIN = function (data)
  3934. {
  3935. if (!Array.isArray(data))
  3936. {
  3937. if (this.IsNumber(data)) return Math.acos(data);
  3938. return null;
  3939. }
  3940. else
  3941. {
  3942. var result = [];
  3943. for (let i in data)
  3944. {
  3945. var item = data[i];
  3946. result[i] = null;
  3947. if (this.IsNumber(item))
  3948. {
  3949. if (item >= -1 && item <= 1)
  3950. {
  3951. result[i] = Math.asin(item);
  3952. }
  3953. else if (i - 1 >= 0)
  3954. {
  3955. var preItem = result[i - 1];
  3956. if (this.IsNumber(preItem)) result[i] = preItem;
  3957. }
  3958. }
  3959. }
  3960. return result;
  3961. }
  3962. }
  3963. //反余弦值. 用法: ACOS(X)返回X的反余弦值
  3964. this.ACOS = function (data)
  3965. {
  3966. if (!Array.isArray(data))
  3967. {
  3968. if (this.IsNumber(data)) return Math.acos(data);
  3969. return null;
  3970. }
  3971. else
  3972. {
  3973. var result = [];
  3974. for (let i in data)
  3975. {
  3976. var item = data[i];
  3977. result[i] = null;
  3978. if (this.IsNumber(item))
  3979. {
  3980. if (item >= -1 && item <= 1)
  3981. {
  3982. result[i] = Math.acos(item);
  3983. }
  3984. else if (i - 1 >= 0) //超出范围使用上一个数值
  3985. {
  3986. var preItem = result[i - 1];
  3987. if (this.IsNumber(preItem)) result[i] = preItem;
  3988. }
  3989. }
  3990. }
  3991. return result;
  3992. }
  3993. }
  3994. /*
  3995. LAST(X,A,B):持续存在.
  3996. 用法:
  3997. LAST(CLOSE>OPEN,10,5)
  3998. 表示从前10日到前5日内一直阳线
  3999. 若A为0,表示从第一天开始,B为0,表示到最后日止
  4000. */
  4001. this.LAST = function (data, n, n2)
  4002. {
  4003. var result = [];
  4004. if (n2 <= 0) n2 = data.length - 1;
  4005. if (n2 > n) return result;
  4006. var day = 0;
  4007. for (let i = 0, j = 0; i < data.length; ++i) {
  4008. result[i] = 0;
  4009. day = 0;
  4010. var start = i - n;
  4011. var end = i - n2;
  4012. if (start < 0 || end < 0) continue;
  4013. for (j = start; j < data.length && j <= end; ++j, ++day) {
  4014. if (!data[j]) break;
  4015. }
  4016. if (day == end - start + 1) //[start,end]
  4017. result[i] = 1;
  4018. }
  4019. return result;
  4020. }
  4021. /*
  4022. 属于未来函数,之字转向.
  4023. 用法: ZIG(K,N),当价格变化量超过N%时转向,K表示0:开盘价,1:最高价,2:最低价,3:收盘价,其余:数组信息
  4024. 例如: ZIG(3,5)表示收盘价的5%的ZIG转向
  4025. */
  4026. this.ZIG=function(data,n)
  4027. {
  4028. var hisData=this.SymbolData.Data;
  4029. var result=[];
  4030. if (typeof(data)=='number')
  4031. {
  4032. switch(data)
  4033. {
  4034. case 0:
  4035. data=hisData.GetOpen();
  4036. break;
  4037. case 1:
  4038. data=hisData.GetHigh();
  4039. break;
  4040. case 2:
  4041. data=hisData.GetLow();
  4042. break;
  4043. case 3:
  4044. data=hisData.GetClose();
  4045. break;
  4046. default:
  4047. return result;
  4048. }
  4049. }
  4050. return this.ZIG_Calculate(data,n);
  4051. }
  4052. this.ZIG_Calculate=function(data,dRate)
  4053. {
  4054. var dest=[];
  4055. var nDataCount=data.length;
  4056. var m=this.GetFirstVaildIndex(data);
  4057. var i = 0, lLastPos = 0, lState = 0, j = 0;
  4058. var dif = 0;
  4059. for (i = m + 1, lLastPos = lState = m; i<nDataCount - 1 && lState == m; ++i)
  4060. {
  4061. lState = Math.abs(data[i] - data[m]) * 100 >= dRate*data[m] ? (data[i]>data[m] ? i : -i) : m;
  4062. }
  4063. for (; i<nDataCount - 1; ++i)
  4064. {
  4065. if (data[i] >= data[i - 1] && data[i] >= data[i + 1])
  4066. {
  4067. if (lState<0)
  4068. {
  4069. if ((data[i] - data[-lState]) * 100<dRate*data[-lState]) continue;
  4070. else
  4071. {
  4072. dif = (data[lLastPos] - data[j = -lState]) / (-lState - lLastPos);
  4073. dest[j--]=data[-lState];
  4074. for (; j >= lLastPos; j--)
  4075. dest[j]=data[-lState] + (-lState - j)*dif;
  4076. lLastPos = -lState;
  4077. lState = i;
  4078. }
  4079. }
  4080. else if (data[i]>data[lState]) lState = i;
  4081. }
  4082. else if (data[i] <= data[i - 1] && data[i] <= data[i + 1])
  4083. {
  4084. if (lState>0)
  4085. {
  4086. if ((data[lState] - data[i]) * 100<dRate*data[lState]) continue;
  4087. else
  4088. {
  4089. dif = (data[lState] - data[j = lLastPos]) / (lState - lLastPos);
  4090. dest[j++]=data[lLastPos];
  4091. for (; j <= lState; ++j)
  4092. dest[j]=data[lLastPos] + (j - lLastPos)*dif;
  4093. lLastPos = lState;
  4094. lState = -i;
  4095. }
  4096. }
  4097. else if (data[i]<data[-lState]) lState = -i;
  4098. }
  4099. }
  4100. if (Math.abs(lState) >= nDataCount - 2)
  4101. {
  4102. if (lState>0 && data[nDataCount - 1] >= data[lState]) lState = nDataCount - 1;
  4103. if (lState<0 && data[nDataCount - 1] <= data[-lState]) lState = 1 - nDataCount;
  4104. }
  4105. if (lState>0)
  4106. {
  4107. dif = (data[lState] - data[j = lLastPos]) / (lState - lLastPos );
  4108. dest[j++]=data[lLastPos];
  4109. for (; j <= lState; ++j)
  4110. dest[j]=data[lLastPos] + (j - lLastPos)*dif;
  4111. }
  4112. else
  4113. {
  4114. dif = (data[lLastPos] - data[j = -lState]) / (-lState - lLastPos);
  4115. dest[j--]=data[-lState];
  4116. for (; j >= lLastPos; j--)
  4117. dest[j]=(data[-lState] + (-lState - j)*dif);
  4118. }
  4119. if ((lState = Math.abs(lState))<nDataCount - 1)
  4120. {
  4121. if (data[nDataCount - 1] >= data[lState])
  4122. {
  4123. dif = (data[nDataCount - 1] - data[j = lState]) / (nDataCount - lState);
  4124. dest[j++]=(data[lState]);
  4125. for (; j<nDataCount; ++j)
  4126. dest[j]=(data[lState] + (j - lState)*dif);
  4127. }
  4128. else
  4129. {
  4130. dif = (data[lState] - data[j = nDataCount - 1]) / (nDataCount - lState);
  4131. dest[j--]=(data[nDataCount - 1]);
  4132. for (; j >= lState; j--)
  4133. dest[j]=(data[nDataCount - 1] + (nDataCount - j)*dif);
  4134. }
  4135. }
  4136. return dest;
  4137. }
  4138. this.GetFirstVaildIndex=function(data)
  4139. {
  4140. for (var i = 0; i <data.length; ++i)
  4141. {
  4142. if (this.IsNumber(data[i]))
  4143. return i;
  4144. }
  4145. return data.length;
  4146. }
  4147. this.JSDraw = null;
  4148. this.CalculateZIGLine = function (firstData, secondData, thridData, data, result)
  4149. {
  4150. if (this.JSDraw == null) this.JSDraw = new JSDraw(this.ErrorHandler);
  4151. var isUp = secondData.Up;
  4152. var findData = firstData;
  4153. if (isUp)
  4154. {
  4155. for (var i = firstData.ID + 1; i < thridData.ID; ++i) //查找最高点
  4156. {
  4157. var subItem = data[i];
  4158. if (!this.IsNumber(subItem)) continue;
  4159. if (findData.Value < subItem) findData = { ID: i, Value: subItem };
  4160. }
  4161. }
  4162. else
  4163. {
  4164. for (var i = firstData.ID + 1; i < thridData.ID; ++i) //查找最低点
  4165. {
  4166. var subItem = data[i];
  4167. if (!this.IsNumber(subItem)) continue;
  4168. if (findData.Value > subItem) findData = { ID: i, Value: subItem };
  4169. }
  4170. }
  4171. secondData.Value = findData.Value;
  4172. secondData.ID = findData.ID;
  4173. var lineCache = { Start: { ID: firstData.ID, Value: firstData.Value }, End: { ID: secondData.ID, Value: secondData.Value } };
  4174. var lineData = this.JSDraw.CalculateDrawLine(lineCache);//计算2个点的线上 其他点的数值
  4175. for (var i in lineData)
  4176. {
  4177. var lineItem = lineData[i];
  4178. result[lineItem.ID] = lineItem.Value;
  4179. }
  4180. if (thridData.ID == data.length - 1) //最后一组数据
  4181. {
  4182. //最后2个点的数据连成线
  4183. lineCache = { Start: { ID: secondData.ID, Value: secondData.Value }, End: { ID: thridData.ID, Value: thridData.Value } };
  4184. lineData = this.JSDraw.CalculateDrawLine(lineCache);//计算2个点的线上 其他点的数值
  4185. for (var i in lineData)
  4186. {
  4187. var lineItem = lineData[i];
  4188. result[lineItem.ID] = lineItem.Value;
  4189. }
  4190. }
  4191. else
  4192. {
  4193. firstData.ID = secondData.ID;
  4194. firstData.Value = secondData.Value;
  4195. secondData.ID = thridData.ID;
  4196. secondData.Value = thridData.Value;
  4197. secondData.Up = firstData.Value < secondData.Value;
  4198. }
  4199. }
  4200. /*
  4201. 属于未来函数,前M个ZIG转向波谷到当前距离.
  4202. 用法:
  4203. TROUGHBARS(K,N,M)表示之字转向ZIG(K,N)的前M个波谷到当前的周期数,M必须大于等于1
  4204. 例如:
  4205. TROUGHBARS(2,5,2)表示%5最低价ZIG转向的前2个波谷到当前的周期数
  4206. */
  4207. this.TROUGHBARS=function(data,n,n2)
  4208. {
  4209. var zigData=this.ZIG(data,n); //计算ZIG
  4210. var dest=[];
  4211. var lEnd =n2;
  4212. if (lEnd<1) return dest;
  4213. var nDataCount = zigData.length;
  4214. var trough = [];
  4215. for(var i=0;i<lEnd;++i) trough[i]=0;
  4216. var lFlag = 0;
  4217. var i = this.GetFirstVaildIndex(zigData) + 1;
  4218. for (lEnd--; i<nDataCount && zigData[i]>zigData[i - 1]; ++i);
  4219. for (; i<nDataCount && zigData[i]<zigData[i - 1]; ++i);
  4220. for (trough[0] = --i; i<nDataCount - 1; ++i)
  4221. {
  4222. if (zigData[i]<zigData[i + 1])
  4223. {
  4224. if (lFlag)
  4225. {
  4226. if (lEnd)
  4227. {
  4228. var tempTrough=trough.slice(0);
  4229. for(var j=0;j<lEnd;++j)
  4230. {
  4231. trough[j+1]=tempTrough[j];
  4232. }
  4233. }
  4234. trough[lFlag = 0] = i;
  4235. }
  4236. }
  4237. else lFlag = 1;
  4238. if (trough[lEnd]) dest[i]=(i - trough[lEnd]);
  4239. }
  4240. if (trough[lEnd]) dest[i]=(i - trough[lEnd]);
  4241. return dest;
  4242. }
  4243. this.TROUGH=function(data,n,n2)
  4244. {
  4245. var zigData=this.ZIG(data,n); //计算ZIG
  4246. var dest=[];
  4247. var End=n2;
  4248. if(End<1) return dest;
  4249. var nDataCount = zigData.length;
  4250. var trough=[];
  4251. for(var i=0;i<End;++i) trough[i]=0;
  4252. var i=1,Flag=0;
  4253. var i = this.GetFirstVaildIndex(zigData) + 1;
  4254. for(End--; i<nDataCount && zigData[i]>zigData[i-1]; ++i);
  4255. for(; i<nDataCount && zigData[i]<zigData[i-1]; ++i);
  4256. for(trough[0]=--i;i<nDataCount-1;++i)
  4257. {
  4258. if(zigData[i]<zigData[i+1])
  4259. {
  4260. if(Flag)
  4261. {
  4262. if(End)
  4263. {
  4264. var tempTrough=trough.slice(0);
  4265. for(var j=0;j<End;++j)
  4266. {
  4267. trough[j+1]=tempTrough[j];
  4268. }
  4269. }
  4270. trough[Flag=0]=i;
  4271. }
  4272. }
  4273. else Flag=1;
  4274. if(trough[End]) dest[i]=zigData[trough[End]];
  4275. }
  4276. if(trough[End]) dest[i]=zigData[trough[End]];
  4277. return dest;
  4278. }
  4279. /*
  4280. 属于未来函数,前M个ZIG转向波峰到当前距离.
  4281. 用法:
  4282. PEAKBARS(K,N,M)表示之字转向ZIG(K,N)的前M个波峰到当前的周期数,M必须大于等于1
  4283. 例如:
  4284. PEAKBARS(0,5,1)表示%5开盘价ZIG转向的上一个波峰到当前的周期数
  4285. */
  4286. this.PEAKBARS=function(data,n,n2)
  4287. {
  4288. var zigData=this.ZIG(data,n); //计算ZIG
  4289. var dest=[];
  4290. var nDataCount = zigData.length;
  4291. var lEnd = n2;
  4292. if (lEnd < 1) return dest;
  4293. var peak = [];
  4294. for(var i=0;i<lEnd;++i) peak[i]=0;
  4295. var lFlag = 0;
  4296. var i = this.GetFirstVaildIndex(zigData) + 1;
  4297. for (lEnd--; i<nDataCount && zigData[i]<zigData[i - 1]; ++i);
  4298. for (; i<nDataCount && zigData[i]>zigData[i - 1]; ++i);
  4299. for (peak[0] = --i; i<nDataCount - 1; ++i)
  4300. {
  4301. if (zigData[i]>zigData[i + 1])
  4302. {
  4303. if (lFlag)
  4304. {
  4305. if (lEnd)
  4306. {
  4307. var tempPeak=peak.slice(0);
  4308. for(var j=0;j<lEnd;++j)
  4309. {
  4310. peak[j+1]=tempPeak[j];
  4311. }
  4312. }
  4313. peak[lFlag = 0] = i;
  4314. }
  4315. }
  4316. else lFlag = 1;
  4317. if (peak[lEnd]) dest[i]=(i - peak[lEnd]);
  4318. }
  4319. if (peak[lEnd])dest[i]=(i - peak[lEnd]);
  4320. return dest;
  4321. }
  4322. this.PEAK=function(data,n,n2)
  4323. {
  4324. var zigData=this.ZIG(data,n); //计算ZIG
  4325. var dest=[];
  4326. var nDataCount = zigData.length;
  4327. var lEnd = n2;
  4328. if (lEnd < 1) return dest;
  4329. var lFlag = 0;
  4330. var peak = [];
  4331. for(var i=0;i<lEnd;++i) peak[i]=0;
  4332. var i = this.GetFirstVaildIndex(zigData) + 1;
  4333. for (lEnd--; i<nDataCount && zigData[i]<zigData[i - 1]; ++i);
  4334. for (; i<nDataCount && zigData[i]>zigData[i - 1]; ++i);
  4335. for (peak[0] = --i; i<nDataCount - 1; ++i)
  4336. {
  4337. if (zigData[i]>zigData[i + 1])
  4338. {
  4339. if (lFlag)
  4340. {
  4341. if (lEnd)
  4342. {
  4343. var tempPeak=peak.slice(0);
  4344. for(var j=0;j<lEnd;++j)
  4345. {
  4346. peak[j+1]=tempPeak[j];
  4347. }
  4348. }
  4349. peak[lFlag = 0] = i;
  4350. }
  4351. }
  4352. else lFlag = 1;
  4353. if (peak[lEnd]) dest[i]=(zigData[peak[lEnd]]);
  4354. }
  4355. if (peak[lEnd]) dest[i]=(zigData[peak[lEnd]]);
  4356. return dest;
  4357. }
  4358. /*
  4359. 一直存在.
  4360. 例如:
  4361. EVERY(CLOSE>OPEN,N)
  4362. 表示N日内一直阳线(N应大于0,小于总周期数,N支持变量)
  4363. */
  4364. this.EVERY = function (data, n)
  4365. {
  4366. var result=[];
  4367. if (n<1) return result;
  4368. if (IFrameSplitOperator.IsNumber(n))
  4369. {
  4370. n=parseInt(n);
  4371. var i=0;
  4372. for(;i<data.length;++i)
  4373. {
  4374. result[i]=null;
  4375. if (this.IsNumber(data[i])) break;
  4376. }
  4377. var flag=0;
  4378. for(;i<data.length;++i)
  4379. {
  4380. if (data[i]) flag+=1;
  4381. else flag=0;
  4382. if (flag==n)
  4383. {
  4384. result[i]=1;
  4385. --flag;
  4386. }
  4387. else
  4388. {
  4389. result[i]=0;
  4390. }
  4391. }
  4392. }
  4393. else if (Array.isArray(n))
  4394. {
  4395. for(var i=0;i<n.length;++i)
  4396. {
  4397. var value=n[i];
  4398. result[i]=null;
  4399. if (!IFrameSplitOperator.IsPlusNumber(value)) continue;
  4400. value=parseInt(value);
  4401. var flag=0;
  4402. for(var j=i, k=0; j>=0 && k<value; --j, ++k)
  4403. {
  4404. if (data[j]) ++flag;
  4405. }
  4406. result[i]=(flag==value?1:0);
  4407. }
  4408. }
  4409. return result;
  4410. }
  4411. /*
  4412. 成本分布情况.
  4413. 用法:
  4414. COST(10),表示10%获利盘的价格是多少,即有10%的持仓量在该价格以下,其余90%在该价格以上,为套牢盘
  4415. 该函数仅对日线分析周期有效
  4416. */
  4417. this.COST = function (data, node)
  4418. {
  4419. var result=[];
  4420. var rate=data/100;
  4421. if(rate<0.000001 || rate>1) return result;
  4422. var kData=this.SymbolData.Data.Data;
  4423. if (!kData || kData.length<=0) return result;
  4424. var aryCapital=this.SymbolData.GetStockCacheData({ FunctionName:"FINANCE", Args:[7], ArgCount:1, Node:node } ); //流通股本
  4425. var dMaxPrice=kData[0].High,dMinPrice=kData[0].Low;
  4426. for(var i=0;i<kData.length;++i)
  4427. {
  4428. var item=kData[i];
  4429. dMinPrice = Math.min(dMinPrice,item.Low);
  4430. dMaxPrice = Math.max(dMaxPrice,item.High);
  4431. }
  4432. if (dMinPrice > 5000 || dMinPrice < 0 || dMaxPrice>5000 || dMinPrice < 0)
  4433. this.ThrowUnexpectedNode(node,'COST() 历史K线最大最小值错误, 超出(0,5000)范围');
  4434. var lMaxPrice = parseInt(dMaxPrice * 100 + 1);
  4435. var lMinPrice = parseInt(dMinPrice * 100 - 1);
  4436. var lLow = 0, lHigh = 0, lClose = 0;
  4437. //去掉小数
  4438. dMaxPrice = lMaxPrice / 100.0;
  4439. dMinPrice = lMinPrice / 100.0;
  4440. var lSpeed = lMaxPrice - lMinPrice + 1;
  4441. if (lSpeed < 1) return result;
  4442. var aryVolPrice=[],aryPerVol=[];
  4443. for(var i=0;i<lSpeed;++i)
  4444. {
  4445. aryVolPrice[i]=0;
  4446. aryPerVol[i]=0;
  4447. }
  4448. var dHSL = 0, dTotalVol = 0, dVol = 0, dCost=0;
  4449. for(var i=0;i<kData.length;++i)
  4450. {
  4451. if (i >= aryCapital.length) continue;
  4452. if (aryCapital[i]>1)
  4453. {
  4454. var kItem=kData[i]
  4455. dHSL = kItem.Vol/aryCapital[i];
  4456. for( var j=0;j<lSpeed;j++)
  4457. aryVolPrice[j]*=(1-dHSL);
  4458. lLow=parseInt(Math.min(lMaxPrice,Math.max(lMinPrice,kItem.Low *100)))-lMinPrice;
  4459. lHigh=parseInt(Math.min(lMaxPrice,Math.max(lMinPrice,kItem.High*100)))-lMinPrice;
  4460. lClose=parseInt(Math.min(lMaxPrice,Math.max(lMinPrice,kItem.Close*100)))-lMinPrice;
  4461. for(var j=0;j<lSpeed;++j) aryPerVol[j]=0;
  4462. var lHalf =parseInt((lLow + lHigh + 2 * lClose) / 4);
  4463. if (lHalf == lHigh || lHalf == lLow)
  4464. {
  4465. aryPerVol[lHalf] += kItem.Vol;
  4466. }
  4467. else
  4468. {
  4469. var dVH = kItem.Vol / (lHalf - lLow);
  4470. for (var k = lLow; k<lHalf; ++k)
  4471. {
  4472. aryPerVol[k] += (k - lLow)*(dVH / (lHalf - lLow));
  4473. }
  4474. for (k; k <= lHigh; ++k)
  4475. {
  4476. aryPerVol[k] += (k - lHigh)*(dVH / (lHalf - lHigh));
  4477. }
  4478. }
  4479. var dTotalVol = 0;
  4480. for (var j = lLow; j <= lHigh; j++)
  4481. {
  4482. aryVolPrice[j] += aryPerVol[j];
  4483. }
  4484. for (var j = 0; j < lSpeed; j++)
  4485. {
  4486. dTotalVol += aryVolPrice[j];
  4487. }
  4488. for(j=0,dCost=dVol=0;j<lSpeed;++j)
  4489. {
  4490. dVol+=aryVolPrice[j];
  4491. if(dVol>=dTotalVol*rate)
  4492. {
  4493. dCost=(dMaxPrice-dMinPrice)*j/lSpeed+dMinPrice;
  4494. break;
  4495. }
  4496. }
  4497. }
  4498. result[i]=dCost;
  4499. }
  4500. return result;
  4501. }
  4502. /*
  4503. 获利盘比例.
  4504. 用法:
  4505. WINNER(CLOSE),表示以当前收市价卖出的获利盘比例,例如返回0.1表示10%获利盘;WINNER(10.5)表示10.5元价格的获利盘比例
  4506. 该函数仅对日线分析周期有效
  4507. 计算比较耗时间
  4508. */
  4509. this.WINNER = function (data,node)
  4510. {
  4511. var result=[];
  4512. var kData=this.SymbolData.Data.Data;
  4513. if (!kData || kData.length<=0) return result;
  4514. var aryCapital=this.SymbolData.GetStockCacheData({ FunctionName:"FINANCE", Args:[7], ArgCount:1, Node:node } ); //流通股本
  4515. var dMaxPrice=kData[0].High,dMinPrice=kData[0].Low;
  4516. for(var i=0;i<kData.length;++i)
  4517. {
  4518. var item=kData[i];
  4519. dMinPrice = Math.min(dMinPrice,item.Low);
  4520. dMaxPrice = Math.max(dMaxPrice,item.High);
  4521. }
  4522. if (dMinPrice > 5000 || dMinPrice < 0 || dMaxPrice>5000 || dMinPrice < 0)
  4523. this.ThrowUnexpectedNode(node,'WINNER() 历史K线最大最小值错误, 超出(0,5000)范围');
  4524. var lMaxPrice = parseInt(dMaxPrice * 100 + 1);
  4525. var lMinPrice = parseInt(dMinPrice * 100 - 1);
  4526. var lLow = 0, lHigh = 0, lClose = 0;
  4527. //去掉小数
  4528. dMaxPrice = lMaxPrice / 100.0;
  4529. dMinPrice = lMinPrice / 100.0;
  4530. var lSpeed = lMaxPrice - lMinPrice + 1;
  4531. if (lSpeed < 1) return result;
  4532. var aryVolPrice=[],aryPerVol=[];
  4533. for(var i=0;i<lSpeed;++i)
  4534. {
  4535. aryVolPrice[i]=0;
  4536. aryPerVol[i]=0;
  4537. }
  4538. var dHSL = 0, dTotalVol = 0, dVol = 0;
  4539. for(var i=0;i<kData.length;++i)
  4540. {
  4541. if (i >= aryCapital.length) continue;
  4542. if (!(aryCapital[i]>1)) continue;
  4543. var kItem=kData[i]
  4544. dHSL = kItem.Vol/aryCapital[i];
  4545. for( var j=0;j<lSpeed;j++)
  4546. aryVolPrice[j]*=(1-dHSL);
  4547. lLow=parseInt(Math.min(lMaxPrice,Math.max(lMinPrice,kItem.Low *100)))-lMinPrice;
  4548. lHigh=parseInt(Math.min(lMaxPrice,Math.max(lMinPrice,kItem.High*100)))-lMinPrice;
  4549. lClose=parseInt(Math.min(lMaxPrice,Math.max(lMinPrice,kItem.Close*100)))-lMinPrice;
  4550. for(var j=0;j<lSpeed;++j) aryPerVol[j]=0;
  4551. var lHalf =parseInt((lLow + lHigh + 2 * lClose) / 4);
  4552. if (lHalf == lHigh || lHalf == lLow)
  4553. {
  4554. aryPerVol[lHalf] += kItem.Vol;
  4555. }
  4556. else
  4557. {
  4558. var dVH = kItem.Vol / (lHalf - lLow);
  4559. for (var k = lLow; k<lHalf; ++k)
  4560. {
  4561. aryPerVol[k] += (k - lLow)*(dVH / (lHalf - lLow));
  4562. }
  4563. for (k; k <= lHigh; ++k)
  4564. {
  4565. aryPerVol[k] += (k - lHigh)*(dVH / (lHalf - lHigh));
  4566. }
  4567. }
  4568. var dTotalVol = 0;
  4569. for (var j = lLow; j <= lHigh; j++)
  4570. {
  4571. aryVolPrice[j] += aryPerVol[j];
  4572. }
  4573. for (var j = 0; j < lSpeed; j++)
  4574. {
  4575. dTotalVol += aryVolPrice[j];
  4576. }
  4577. if (Array.isArray(data))
  4578. lHigh = parseInt(Math.min((data[i] * 100) - lMinPrice, lSpeed - 1));
  4579. else
  4580. lHigh = parseInt(Math.min((data * 100) - lMinPrice, lSpeed - 1));
  4581. for (var j = 0, dVol = 0; j <= lHigh; j++)
  4582. {
  4583. dVol += aryVolPrice[j];
  4584. }
  4585. if (dTotalVol > 0) result[i]=dVol / dTotalVol;
  4586. else if (i - 1 >= 0) result[i] = result[i - 1];
  4587. }
  4588. return result;
  4589. }
  4590. //计算截至到某一天的历史所有筹码
  4591. this.CalculateChip = function (index, exchangeData, hisData, dRate)
  4592. {
  4593. var result = { Min: null, Max: null, Data: [] };
  4594. var seed = 1;//筹码历史衰减换手系数
  4595. var max = null, min = null;
  4596. for (let i = index; i >= 0; --i)
  4597. {
  4598. let item = {}; //Vol:量 High:最高 Low:最低
  4599. var kData = hisData[i];
  4600. if (i == index) item.Vol = kData.Vol * exchangeData[i];
  4601. else item.Vol = kData.Vol * seed;
  4602. item.Date = kData.Date;
  4603. item.High = kData.High;
  4604. item.Low = kData.Low;
  4605. if (max == null) max = item.High;
  4606. else if (max < item.High) max = item.High;
  4607. if (min == null) min = item.Low;
  4608. else if (min < item.Low) min = item.Low;
  4609. result.Data[i] = item;
  4610. seed *= (1 - (exchangeData[i] / 100) * dRate); //换手率累乘
  4611. }
  4612. result.Max = max;
  4613. result.Min = min;
  4614. return result;
  4615. }
  4616. /*
  4617. 返回是否连涨周期数.
  4618. 用法:
  4619. UPNDAY(CLOSE,M)
  4620. 表示连涨M个周期,M为常量
  4621. */
  4622. this.UPNDAY = function (data, n)
  4623. {
  4624. var result = [];
  4625. if (n < 1) return result;
  4626. if (data == null || n > data.length) return result;
  4627. var days = 0;
  4628. for (let i = 0; i < data.length; ++i)
  4629. {
  4630. result[i] = 0;
  4631. if (i - 1 < 0) continue;
  4632. if (!this.IsNumber(data[i]) || !this.IsNumber(data[i - 1])) //无效数都不算连涨
  4633. {
  4634. days = 0;
  4635. continue;
  4636. }
  4637. if (data[i] > data[i - 1])++days;
  4638. else days = 0;
  4639. if (days == n)
  4640. {
  4641. result[i] = 1;
  4642. --days;
  4643. }
  4644. }
  4645. return result;
  4646. }
  4647. /*
  4648. 返回是否连跌周期.
  4649. 用法:
  4650. DOWNNDAY(CLOSE,M)
  4651. 表示连跌M个周期,M为常量
  4652. */
  4653. this.DOWNNDAY = function (data, n)
  4654. {
  4655. var result = [];
  4656. if (n < 1) return result;
  4657. if (data == null || n > data.length) return result;
  4658. var days = 0;
  4659. for (let i = 0; i < data.length; ++i)
  4660. {
  4661. result[i] = 0;
  4662. if (i - 1 < 0) continue;
  4663. if (!this.IsNumber(data[i]) || !this.IsNumber(data[i - 1])) //无效数都不算连涨
  4664. {
  4665. days = 0;
  4666. continue;
  4667. }
  4668. if (data[i] < data[i - 1])++days;
  4669. else days = 0;
  4670. if (days == n)
  4671. {
  4672. result[i] = 1;
  4673. --days;
  4674. }
  4675. }
  4676. return result;
  4677. }
  4678. /*
  4679. 返回是否持续存在X>Y
  4680. 用法:
  4681. NDAY(CLOSE,OPEN,3)
  4682. 表示连续3日收阳线
  4683. */
  4684. this.NDAY = function (data, data2, n)
  4685. {
  4686. var result = [];
  4687. if (n < 1) return result;
  4688. if (!Array.isArray(data) && !Array.isArray(data2)) return result;
  4689. if (data == null || data2 == null) return result;
  4690. if (Array.isArray(data) && Array.isArray(data2))
  4691. {
  4692. if (n >= data.length || n >= data2.length) return result;
  4693. var count = Math.max(data.length, data2.length);
  4694. var days = 0;
  4695. for (let i = 0; i < count; ++i)
  4696. {
  4697. result[i] = 0;
  4698. if (i >= data.length || i >= data2.length) continue;
  4699. if (!this.IsNumber(data[i]) || !this.IsNumber(data2[i]))
  4700. {
  4701. days = 0;
  4702. continue;
  4703. }
  4704. if (data[i] > data2[i])++days;
  4705. else days = 0;
  4706. if (days == n)
  4707. {
  4708. result[i] = 1;
  4709. --days;
  4710. }
  4711. }
  4712. }
  4713. else if (Array.isArray(data) && !Array.isArray(data2))
  4714. {
  4715. if (n >= data.length || !this.IsNumber(data2)) return;
  4716. var days = 0;
  4717. for (let i in data)
  4718. {
  4719. result[i] = 0;
  4720. if (!this.IsNumber(data[i]))
  4721. {
  4722. days = 0;
  4723. continue;
  4724. }
  4725. if (data[i] > data2)++days;
  4726. else days = 0;
  4727. if (days == n)
  4728. {
  4729. result[i] = 1;
  4730. --days;
  4731. }
  4732. }
  4733. }
  4734. else if (!Array.isArray(data) && Array.isArray(data2))
  4735. {
  4736. if (n >= data2.length || !this.IsNumber(data)) return;
  4737. var days = 0;
  4738. for (let i in data2)
  4739. {
  4740. result[i] = 0;
  4741. if (!this.IsNumber(data2[i]))
  4742. {
  4743. days = 0;
  4744. continue;
  4745. }
  4746. if (data > data2[i])++days;
  4747. else days = 0;
  4748. if (days == n)
  4749. {
  4750. result[i] = 1;
  4751. --days;
  4752. }
  4753. }
  4754. }
  4755. return result;
  4756. }
  4757. /*
  4758. 两条线维持一定周期后交叉.
  4759. 用法:LONGCROSS(A,B,N)表示A在N周期内都小于B,本周期从下方向上穿过B时返回1,否则返回0
  4760. */
  4761. this.LONGCROSS = function (data, data2, n)
  4762. {
  4763. var result = [];
  4764. var count = Math.max(data.length, data2.length);
  4765. for (let i = 0; i < count; ++i)
  4766. {
  4767. result[i] = 0;
  4768. if (i - 1 < 0) continue;
  4769. if (i >= data.length || i >= data2.length) continue;
  4770. if (!this.IsNumber(data[i]) || !this.IsNumber(data2[i]) || !this.IsNumber(data[i - 1]) || !this.IsNumber(data2[i - 1])) continue;
  4771. if (data[i] > data2[i] && data[i - 1] < data2[i - 1]) result[i] = 1;
  4772. }
  4773. for (let i = 0, j = 0; i < count; ++i)
  4774. {
  4775. if (!result[i]) continue;
  4776. for (j = 1; j <= n && i - j >= 0; ++j)
  4777. {
  4778. if (data[i - j] >= data2[i - j])
  4779. {
  4780. result[i] = 0;
  4781. break;
  4782. }
  4783. }
  4784. }
  4785. return result;
  4786. }
  4787. this.ISVALID=function(data)
  4788. {
  4789. if (Array.isArray(data))
  4790. {
  4791. var result=[];
  4792. for(var i=0;i<data.length;++i)
  4793. {
  4794. var item=data[i];
  4795. if (item) result[i]=1;
  4796. else result[i]=0;
  4797. }
  4798. return result;
  4799. }
  4800. else
  4801. {
  4802. if (data) return 1;
  4803. else return 0;
  4804. }
  4805. }
  4806. /*
  4807. EXISTR(X,A,B):是否存在(前几日到前几日间).
  4808. 例如: EXISTR(CLOSE>OPEN,10,5)
  4809. 表示从前10日内到前5日内存在着阳线
  4810. 若A为0,表示从第一天开始,B为0,表示到最后日止
  4811. */
  4812. this.EXISTR = function (data, n, n2)
  4813. {
  4814. var result = [];
  4815. if (!Array.isArray(data)) return result;
  4816. n = parseInt(n);
  4817. n2 = parseInt(n2);
  4818. if (n <= 0) n = data.length;
  4819. if (n2 <= 0) n2 = 1;
  4820. if (n2 > n) return result;
  4821. var result = [];
  4822. var value;
  4823. for (let i = 0, j = 0; i < data.length; ++i)
  4824. {
  4825. result[i] = null;
  4826. if (i - n < 0 || i - n2 < 0) continue;
  4827. result[i] = 0;
  4828. for (j = n; j >= n2; --j)
  4829. {
  4830. var value = data[i - j];
  4831. if (this.IsNumber(value) && value)
  4832. {
  4833. result[i] = 1;
  4834. break;
  4835. }
  4836. }
  4837. }
  4838. return result;
  4839. }
  4840. /*
  4841. RELATE(X,Y,N) 返回X和Y的N周期的相关系数
  4842. RELATE(X,Y,N)=([(Xi-Avg(X))(Yi-Avg(y))])/N ÷ (((Xi-Avg(X))^2)/N * ((Yi-Avg(Y))^2)/N)
  4843. 其中 avg(x)表示x的N周期均值 avg(X) = (Xi)/N
  4844. (...)表示开平方
  4845. */
  4846. this.RELATE = function (data, data2, n)
  4847. {
  4848. var result = [];
  4849. if (n < 1) n = 1;
  4850. if (!Array.isArray(data) || !Array.isArray(data2)) return result;
  4851. var dataAverage = this.CalculateAverage(data, n);
  4852. var data2Average = this.CalculateAverage(data2, n);
  4853. var count = Math.max(data.length, data2.length);
  4854. for (let i = 0, j = 0; i < count; ++i)
  4855. {
  4856. result[i] = null;
  4857. if (i >= data.length || i >= data2.length || i >= dataAverage.length || i >= data2Average.length) continue;
  4858. var average = dataAverage[i];
  4859. var average2 = data2Average[i];
  4860. var total = 0, total2 = 0, total3 = 0;
  4861. for (j = i - n + 1; j <= i; ++j)
  4862. {
  4863. total += (data[j] - average) * (data2[j] - average2); //∑[(Xi-Avg(X))(Yi-Avg(y))])
  4864. total2 += Math.pow(data[j] - average, 2); //∑(Xi-Avg(X))^2
  4865. total3 += Math.pow(data2[j] - average2, 2); //∑(Yi-Avg(Y))^2)
  4866. }
  4867. result[i] = (total / n) / (Math.sqrt(total2 / n) * Math.sqrt(total3 / n));
  4868. }
  4869. return result;
  4870. }
  4871. //计算数组n周期内的均值
  4872. this.CalculateAverage = function (data, n)
  4873. {
  4874. var result = [];
  4875. if (n < 1) return result;
  4876. var total = 0;
  4877. for (var i = 0; i < data.length; ++i) //去掉开始的无效数
  4878. {
  4879. if (this.IsNumber(data[i])) break;
  4880. }
  4881. for (; i < data.length && i < n; ++i) //计算第1个周期的数据
  4882. {
  4883. result[i] = null;
  4884. var value = data[i];
  4885. if (!this.IsNumber(value)) continue;
  4886. total += value;
  4887. }
  4888. result[i - 1] = total / n;
  4889. for (; i < data.length; ++i) //计算后面的周期数据
  4890. {
  4891. var value = data[i];
  4892. var preValue = data[i - n]; //上一个周期的第1个数据
  4893. if (!this.IsNumber(value)) value = 0;
  4894. if (!this.IsNumber(preValue)) preValue = 0;
  4895. total = total - preValue + value; //当前周期的数据 等于上一个周期数据 去掉上一个周期的第1个数据 加上这个周期的最后1个数据
  4896. result[i] = total / n;
  4897. }
  4898. return result;
  4899. }
  4900. /*
  4901. COVAR(X,Y,N) 返回X和Y的N周期的协方差
  4902. */
  4903. this.COVAR = function (data, data2, n)
  4904. {
  4905. if (this.IsNumber(data) || this.IsNumber(data2)) return 0;
  4906. var result = [];
  4907. if (n < 1) n = 1;
  4908. if (!Array.isArray(data) || !Array.isArray(data2)) return result;
  4909. var dataAverage = this.CalculateAverage(data, n);
  4910. var data2Average = this.CalculateAverage(data2, n);
  4911. var count = Math.max(data.length, data2.length);
  4912. var count = Math.max(data.length, data2.length);
  4913. for (let i = 0, j = 0; i < count; ++i)
  4914. {
  4915. result[i] = null;
  4916. if (i >= data.length || i >= data2.length || i >= dataAverage.length || i >= data2Average.length) continue;
  4917. var average = dataAverage[i];
  4918. var average2 = data2Average[i];
  4919. var total = 0;
  4920. for (j = i - n + 1; j <= i; ++j)
  4921. {
  4922. total += (data[j] - average) * (data2[j] - average2);
  4923. }
  4924. result[i] = (total / n);
  4925. }
  4926. return result;
  4927. }
  4928. /*
  4929. 求上一高点到当前的周期数.
  4930. 用法:
  4931. HHVBARS(X,N):求N周期内X最高值到当前周期数,N=0表示从第一个有效值开始统计
  4932. 例如:
  4933. HHVBARS(HIGH,0)求得历史新高到到当前的周期数
  4934. */
  4935. this.HHVBARS = function (data, n)
  4936. {
  4937. var result = [];
  4938. if (!Array.isArray(data)) return result;
  4939. if (Array.isArray(n))
  4940. {
  4941. for(var i=0;i<n.length;++i)
  4942. {
  4943. result[i]=null;
  4944. var period=n[i];
  4945. if (!this.IsNumber(period)) continue;
  4946. var start=i-period;
  4947. if (start<0) start=0;
  4948. var nMax=null;
  4949. var j=start;
  4950. for(; j<data.length;++j)
  4951. {
  4952. if (this.IsNumber(data[j]))
  4953. {
  4954. nMax=j;
  4955. break;
  4956. }
  4957. }
  4958. for(var k=0; j<data.length && k<period;++k, ++j)
  4959. {
  4960. if (data[j]>=data[nMax]) nMax=j;
  4961. }
  4962. if (nMax!=null)
  4963. result[i]=(i-nMax);
  4964. }
  4965. }
  4966. else
  4967. {
  4968. if (n < 1) n = data.length;
  4969. var nMax = null; //最大值索引
  4970. for (var i = 0; i < data.length; ++i)
  4971. {
  4972. result[i] = null;
  4973. if (this.IsNumber(data[i])) {
  4974. nMax = i;
  4975. break;
  4976. }
  4977. }
  4978. var j = 0;
  4979. for (i = nMax + 1; i < data.length && j < n; ++i, ++j) //求第1个最大值
  4980. {
  4981. if (data[i] >= data[nMax]) nMax = i;
  4982. if (n == data.length) result[i] = (i - nMax);
  4983. }
  4984. for (; i < data.length; ++i)
  4985. {
  4986. if (i - nMax < n)
  4987. {
  4988. if (data[i] >= data[nMax]) nMax = i;
  4989. }
  4990. else
  4991. {
  4992. nMax = i - n + 1;
  4993. for (j = nMax; j <= i; ++j) //计算区间最大值
  4994. {
  4995. if (data[j] >= data[nMax]) nMax = j;
  4996. }
  4997. }
  4998. result[i] = i - nMax;
  4999. }
  5000. }
  5001. return result;
  5002. }
  5003. /*
  5004. 求上一低点到当前的周期数.
  5005. 用法: LLVBARS(X,N):求N周期内X最低值到当前周期数,N=0表示从第一个有效值开始统计
  5006. 例如: LLVBARS(HIGH,20)求得20日最低点到当前的周期数
  5007. */
  5008. this.LLVBARS = function (data, n)
  5009. {
  5010. var result = [];
  5011. if (!Array.isArray(data)) return result;
  5012. if (Array.isArray(n))
  5013. {
  5014. for(var i=0;i<n.length;++i)
  5015. {
  5016. result[i]=null;
  5017. var period=n[i];
  5018. if (!this.IsNumber(period)) continue;
  5019. var start=i-period;
  5020. if (start<0) start=0;
  5021. var nMin=null;
  5022. var j=start;
  5023. for(; j<data.length;++j)
  5024. {
  5025. if (this.IsNumber(data[j]))
  5026. {
  5027. nMin=j;
  5028. break;
  5029. }
  5030. }
  5031. for(var k=0; j<data.length && k<period;++k, ++j)
  5032. {
  5033. if (data[j]<=data[nMin]) nMin=j;
  5034. }
  5035. if (nMin!=null)
  5036. result[i]=(i-nMin);
  5037. }
  5038. }
  5039. else
  5040. {
  5041. if (n < 1) n = data.length;
  5042. var nMin = null; //最小值索引
  5043. for (var i = 0; i < data.length; ++i)
  5044. {
  5045. result[i] = null;
  5046. if (this.IsNumber(data[i]))
  5047. {
  5048. nMin = i;
  5049. break;
  5050. }
  5051. }
  5052. var j = 0;
  5053. for (i = nMin + 1; i < data.length && j < n; ++i, ++j) //求第1个最大值
  5054. {
  5055. if (data[i] <= data[nMin]) nMin = i;
  5056. if (n == data.length) result[i] = (i - nMin);
  5057. }
  5058. for (; i < data.length; ++i)
  5059. {
  5060. if (i - nMin < n)
  5061. {
  5062. if (data[i] <= data[nMin]) nMin = i;
  5063. }
  5064. else
  5065. {
  5066. nMin = i - n + 1;
  5067. for (j = nMin; j <= i; ++j) //计算区间最小值
  5068. {
  5069. if (data[j] <= data[nMin]) nMin = j;
  5070. }
  5071. }
  5072. result[i] = i - nMin;
  5073. }
  5074. }
  5075. return result;
  5076. }
  5077. /*
  5078. β(Beta)系数
  5079. BETA(N) 返回当前证券N周期收益与对应大盘指数收益相比的贝塔系数
  5080. 需要下载上证指数历史数据
  5081. 涨幅(X)=(现价-上一个交易日收盘价/上一个交易日收盘价
  5082. 公式=股票和指数协方差/股票方差
  5083. */
  5084. this.BETA = function (n)
  5085. {
  5086. var result = [];
  5087. var stockData = this.SymbolData.Data;
  5088. var indexData = this.SymbolData.IndexData;
  5089. if (n <= 0) n = 1;
  5090. var stockProfit = []; //股票涨幅
  5091. var indexProfit = []; //指数涨幅
  5092. for (let i = 0; i < stockData.Data.length; ++i)
  5093. {
  5094. stockProfit[i] = 0;
  5095. indexProfit[i] = 0;
  5096. var stockItem = stockData.Data[i];
  5097. var indexItem = indexData.Data[i];
  5098. if (stockItem.Close > 0 && stockItem.YClose > 0) stockProfit[i] = (stockItem.Close - stockItem.YClose) / stockItem.YClose;
  5099. if (indexItem.Close > 0 && indexItem.YClose > 0) indexProfit[i] = (indexItem.Close - indexItem.YClose) / indexItem.YClose;
  5100. }
  5101. //计算均值数组
  5102. var averageStockProfit = this.CalculateAverage(stockProfit, n);
  5103. var averageIndexProfit = this.CalculateAverage(indexProfit, n);
  5104. for (var i = 0, j = 0; i < stockData.Data.length; ++i)
  5105. {
  5106. result[i] = null;
  5107. if (i >= stockProfit.length || i >= indexProfit.length || i >= averageStockProfit.length || i >= averageIndexProfit.length) continue;
  5108. var averageStock = averageStockProfit[i];
  5109. var averageIndex = averageIndexProfit[i];
  5110. var covariance = 0; //协方差
  5111. var variance = 0; //方差
  5112. for (j = i - n + 1; j <= i; ++j)
  5113. {
  5114. var value = (indexProfit[j] - averageIndex);
  5115. var value2 = (stockProfit[j] - averageStock);
  5116. covariance += value * value2;
  5117. variance += value * value;
  5118. }
  5119. if (this.IsDivideNumber(variance) && this.IsNumber(covariance))
  5120. result[i] = covariance / variance; //(covariance/n)/(variance/n)=covariance/variance;
  5121. }
  5122. return result;
  5123. }
  5124. /*
  5125. 用法:BETA2(X,Y,N)为X与Y的N周期相关放大系数,表示Y变化1%,则X将变化N%
  5126. 例如:BETA2(CLOSE,INDEXC,10)表示收盘价与大盘指数之间的10周期相关放大率
  5127. */
  5128. this.BETA2 = function (x, y, n)
  5129. {
  5130. var result = [];
  5131. if (n <= 0) n = 1;
  5132. var xProfit = [null]; //x数据的涨幅
  5133. var yProfit = [null]; //y数据的涨幅
  5134. var count = Math.max(x.length, y.length);
  5135. var lastItem = { X: x[0], Y: y[0] };
  5136. for (var i = 1; i < count; ++i)
  5137. {
  5138. xProfit[i] = 0;
  5139. yProfit[i] = 0;
  5140. var xItem = x[i];
  5141. var yItem = y[i];
  5142. if (lastItem.X > 0) xProfit[i] = (xItem - lastItem.X) / lastItem.X;
  5143. if (lastItem.Y > 0) yProfit[i] = (yItem - lastItem.Y) / lastItem.Y;
  5144. lastItem = { X: xItem, Y: yItem };
  5145. }
  5146. //计算均值数组
  5147. var averageXProfit = this.CalculateAverage(xProfit, n);
  5148. var averageYProfit = this.CalculateAverage(yProfit, n);
  5149. for (var i = 0, j = 0; i < count; ++i)
  5150. {
  5151. result[i] = null;
  5152. if (i >= xProfit.length || i >= yProfit.length || i >= averageXProfit.length || i >= averageYProfit.length) continue;
  5153. var averageX = averageXProfit[i];
  5154. var averageY = averageYProfit[i];
  5155. var covariance = 0; //协方差
  5156. var variance = 0; //方差
  5157. for (j = i - n + 1; j <= i; ++j)
  5158. {
  5159. var value = (xProfit[j] - averageX);
  5160. var value2 = (yProfit[j] - averageY);
  5161. covariance += value * value2;
  5162. variance += value * value;
  5163. }
  5164. if (this.IsDivideNumber(variance) && this.IsNumber(covariance))
  5165. result[i] = covariance / variance; //(covariance/n)/(variance/n)=covariance/variance;
  5166. }
  5167. return result;
  5168. }
  5169. /*
  5170. 抛物转向.
  5171. 用法:
  5172. SAR(N,S,M),N为计算周期,S为步长,M为极值
  5173. 例如:
  5174. SAR(10,2,20)表示计算10日抛物转向,步长为2%,极限值为20%
  5175. */
  5176. this.SAR = function (n, step, exValue)
  5177. {
  5178. var result = [];
  5179. var stockData = this.SymbolData.Data;
  5180. if (n >= stockData.Data.length) return result;
  5181. var high = null, low = null;
  5182. for (var i = 0; i < n; ++i)
  5183. {
  5184. var item = stockData.Data[i];
  5185. if (high == null) high = item.High;
  5186. else if (high < item.High) high = item = high;
  5187. if (low == null) low = item.Low;
  5188. else if (low > item.Low) low = item.Low;
  5189. }
  5190. const SAR_LONG = 0, SAR_SHORT = 1;
  5191. var position = SAR_LONG;
  5192. result[n - 1] = low;
  5193. var nextSar = low, sip = stockData.Data[0].High, af = exValue / 100;
  5194. for (var i = n; i < stockData.Data.length; ++i)
  5195. {
  5196. var ysip = sip;
  5197. var item = stockData.Data[i];
  5198. var yitem = stockData.Data[i - 1];
  5199. if (position == SAR_LONG)
  5200. {
  5201. if (item.Low < result[i - 1])
  5202. {
  5203. position = SAR_SHORT;
  5204. sip = item.Low;
  5205. af = step / 100;
  5206. nextSar = Math.max(item.High, yitem.High);
  5207. nextSar = Math.max(nextSar, ysip + af * (sip - ysip));
  5208. }
  5209. else
  5210. {
  5211. position = SAR_LONG;
  5212. if (item.High > ysip)
  5213. {
  5214. sip = item.High;
  5215. af = Math.min(af + step / 100, exValue / 100);
  5216. }
  5217. nextSar = Math.min(item.Low, yitem.Low);
  5218. nextSar = Math.min(nextSar, result[i - 1] + af * (sip - result[i - 1]));
  5219. }
  5220. }
  5221. else if (position == SAR_SHORT)
  5222. {
  5223. if (item.High > result[i - 1])
  5224. {
  5225. position = SAR_LONG;
  5226. sip = item.High;
  5227. af = step / 100;
  5228. nextSar = Math.min(item.Low, yitem.Low);
  5229. nextSar = Math.min(nextSar, result[i - 1] + af * (sip - ysip));
  5230. }
  5231. else
  5232. {
  5233. position = SAR_SHORT;
  5234. if (item.Low < ysip)
  5235. {
  5236. sip = item.Low;
  5237. af = Math.min(af + step / 100, exValue / 100);
  5238. }
  5239. nextSar = Math.max(item.High, yitem.High);
  5240. nextSar = Math.max(nextSar, result[i - 1] + af * (sip - result[i - 1]));
  5241. }
  5242. }
  5243. result[i] = nextSar;
  5244. }
  5245. return result;
  5246. }
  5247. /*
  5248. 抛物转向点.
  5249. 用法:
  5250. SARTURN(N,S,M),N为计算周期,S为步长,M为极值,若发生向上转向则返回1,若发生向下转向则返回-1,否则为0
  5251. 其用法与SAR函数相同
  5252. */
  5253. this.SARTURN = function (n, step, exValue)
  5254. {
  5255. var result = [];
  5256. var sar = this.SAR(n, step, exValue);
  5257. var stockData = this.SymbolData.Data;
  5258. var index = 0;
  5259. for (index = 0; index < sar.length; ++index)
  5260. {
  5261. if (this.IsNumber(sar[index])) break;
  5262. }
  5263. var flag = 0;
  5264. if (index < stockData.Data.length) flag = stockData.Data[index].Close > sar[index];
  5265. for (var i = index + 1; i < stockData.Data.length; ++i)
  5266. {
  5267. var item = stockData.Data[i];
  5268. if (item.Close < sar[i] && flag) result[i] = -1;
  5269. else result[i] = (item.Close > sar[i] && !flag) ? 1 : 0;
  5270. flag = item.Close > sar[i];
  5271. }
  5272. return result;
  5273. }
  5274. /*
  5275. 属于未来函数,将当前位置到若干周期前的数据设为1.
  5276. 用法:
  5277. BACKSET(X,N),若X非0,则将当前位置到N周期前的数值设为1.
  5278. 例如:
  5279. BACKSET(CLOSE>OPEN,2)若收阳则将该周期及前一周期数值设为1,否则为0
  5280. */
  5281. this.BACKSET = function (condition, n)
  5282. {
  5283. var result = [];
  5284. if (!condition) return result;
  5285. var dataCount = condition.length;
  5286. if (!this.IsNumber(dataCount) || dataCount <= 0) return result;
  5287. if (Array.isArray(n))
  5288. {
  5289. for(var i=0;i<dataCount;++i) //初始化0
  5290. {
  5291. result[i]=0;
  5292. }
  5293. for(var i=0;i<dataCount;++i)
  5294. {
  5295. var value=condition[i];
  5296. var period=n[i];
  5297. if (this.IsNumber(value) && value && this.IsNumber(period))
  5298. {
  5299. for(var j=i,k=0; j>=0 && k<period; --j,++k)
  5300. {
  5301. result[j]=1;
  5302. }
  5303. }
  5304. }
  5305. }
  5306. else
  5307. {
  5308. for (var i = 0; i < dataCount; ++i) //初始化0
  5309. {
  5310. result[i] = 0;
  5311. }
  5312. for (var pos = 0; pos < dataCount; ++pos)
  5313. {
  5314. if (this.IsNumber(condition[pos])) break;
  5315. }
  5316. if (pos == dataCount) return result;
  5317. var num = Math.min(dataCount - pos, Math.max(n, 1));
  5318. for (var i = dataCount - 1, j = 0; i >= 0; --i)
  5319. {
  5320. var value = condition[i];
  5321. if (this.IsNumber(value) && value)
  5322. {
  5323. for (j = i; j > i - num; --j)
  5324. {
  5325. result[j] = 1;
  5326. }
  5327. }
  5328. }
  5329. if (condition[i])
  5330. {
  5331. for (j = i; j >= pos; --j) result[j] = 1;
  5332. }
  5333. }
  5334. return result;
  5335. }
  5336. //STRCAT(A,B):将两个字符串A,B(非序列化)相加成一个字符串C.
  5337. //用法: STRCAT('多头','开仓')将两个字符串'多头','开仓'相加成一个字符串'多头开仓'
  5338. this.STRCAT = function (str1, str2)
  5339. {
  5340. var result=[];
  5341. if (this.IsString(str1) && this.IsString(str2))
  5342. result=str1+str2;
  5343. return result;
  5344. }
  5345. //VARCAT(A,B):将两个字符串A,B相加成一个字符串C.
  5346. //用法: DRAWTEXT(CLOSE>OPEN,LOW,VARCAT('多头',VAR2STR(C,2))) 将两个字符串相加成一个字符串并按条件显示出来
  5347. this.VARCAT=function(data,data2)
  5348. {
  5349. var result=[];
  5350. if (Array.isArray(data) && Array.isArray(data2))
  5351. {
  5352. var nCount=Math.max(data.length, data2.length);
  5353. var strValue="";
  5354. for(var i=0;i<nCount;++i)
  5355. {
  5356. result[i]=null;
  5357. strValue="";
  5358. if (i<data.length)
  5359. {
  5360. var item=data[i];
  5361. if (this.IsString(item))
  5362. strValue+=item;
  5363. }
  5364. if (i<data2.length)
  5365. {
  5366. var item=data2[i];
  5367. if (this.IsString(item))
  5368. strValue+=item;
  5369. }
  5370. if (strValue!="")
  5371. result[i]=strValue;
  5372. }
  5373. }
  5374. else if (this.IsString(data) && Array.isArray(data2))
  5375. {
  5376. for(var i=0;i<data2.length;++i)
  5377. {
  5378. result[i]=null;
  5379. var item=data2[i];
  5380. if (this.IsString(item))
  5381. {
  5382. result[i]=data+item;
  5383. }
  5384. }
  5385. }
  5386. else if (Array.isArray(data) && this.IsString(data2))
  5387. {
  5388. for(var i=0;i<data.length;++i)
  5389. {
  5390. result[i]=null;
  5391. var item=data[i];
  5392. if (this.IsString(item))
  5393. {
  5394. result[i]=item+data2;
  5395. }
  5396. }
  5397. }
  5398. else if (this.IsString(data) && this.IsString(data2))
  5399. {
  5400. result=data+data2;
  5401. }
  5402. return result;
  5403. }
  5404. //FINDSTR(A,B):在字符串A中查找字符串B,如果找到返回1,否则返回0.
  5405. //用法: FINDSTR('多头开仓','开仓')在字符串'多头开仓'中查找字符串'开仓',返回1
  5406. this.FINDSTR=function(data, data2)
  5407. {
  5408. var result=[];
  5409. var str, str2;
  5410. if (IFrameSplitOperator.IsNumber(data)) str=data.toString();
  5411. else str=data;
  5412. if (IFrameSplitOperator.IsNumber(data2)) str2=data2.toString();
  5413. else str2=data2;
  5414. if (IFrameSplitOperator.IsString(str) && IFrameSplitOperator.IsString(str2))
  5415. {
  5416. if (str.indexOf(str2)>=0) return 1;
  5417. else return 0;
  5418. }
  5419. else if (Array.isArray(data) && IFrameSplitOperator.IsString(str2))
  5420. {
  5421. for(var i=0;i<data.length;++i)
  5422. {
  5423. var item=data[i];
  5424. if (IFrameSplitOperator.IsString(item))
  5425. {
  5426. result[i]=item.indexOf(str2)>=0?1:0;
  5427. }
  5428. else if (IFrameSplitOperator.IsNumber(item))
  5429. {
  5430. str=item.toString();
  5431. result[i]=str.indexOf(str2)>=0?1:0;
  5432. }
  5433. else
  5434. {
  5435. result[i]=0;
  5436. }
  5437. }
  5438. }
  5439. return result;
  5440. }
  5441. this.STRLEN=function(data)
  5442. {
  5443. if (IFrameSplitOperator.IsString(data)) return data.length;
  5444. if (Array.isArray(data))
  5445. {
  5446. var result=[];
  5447. for(var i=0;i<data.length;++i)
  5448. {
  5449. var item=data[i];
  5450. if (IFrameSplitOperator.IsString(item)) result[i]=item.length;
  5451. else result[i]=null;
  5452. }
  5453. return result;
  5454. }
  5455. return null;
  5456. }
  5457. this.STRCMP=function(data, data2)
  5458. {
  5459. if (IFrameSplitOperator.IsString(data) && IFrameSplitOperator.IsString(data2))
  5460. {
  5461. return data==data2? 1:0;
  5462. }
  5463. return null;
  5464. }
  5465. //STRSPACE(A):字符串附带一空格
  5466. this.STRSPACE=function(data)
  5467. {
  5468. var result=[];
  5469. if (Array.isArray(data))
  5470. {
  5471. for(var i=0;i<data.length;++i)
  5472. {
  5473. result[i]=null;
  5474. var item=data[i];
  5475. if (TouchList.IsString(item))
  5476. result[i]=item+' ';
  5477. }
  5478. }
  5479. else
  5480. {
  5481. if (this.IsString(data))
  5482. result=data+" ";
  5483. }
  5484. return result;
  5485. }
  5486. //CON2STR(A,N):取A最后的值(非序列值)转为字符串,小数位数N.
  5487. //用法: CON2STR(FINANCE(20),3)表示取营业收入,以3位小数转为字符串
  5488. this.CON2STR = function (data, n)
  5489. {
  5490. var result = [];
  5491. if (Array.isArray(data))
  5492. {
  5493. for (var i = data.length - 1; i >= 0; --i)
  5494. {
  5495. var item = data[i];
  5496. if (this.IsNumber(item))
  5497. {
  5498. result = item.toFixed(n);
  5499. return result;
  5500. }
  5501. }
  5502. }
  5503. else
  5504. {
  5505. if (this.IsNumber(data))
  5506. result = data.toFixed(n);
  5507. }
  5508. return result;
  5509. }
  5510. //VAR2STR(A,N):取A的每一个值转为字符串,小数位数N.
  5511. //用法: VAR2STR(C,3)表示取收盘价,以3位小数转为字符串
  5512. this.VAR2STR=function(data,n)
  5513. {
  5514. var result=[];
  5515. if (Array.isArray(data))
  5516. {
  5517. for(var i=0;i<data.length;++i)
  5518. {
  5519. result[i]=null;
  5520. var item=data[i];
  5521. if (this.IsNumber(item))
  5522. result[i]=item.toFixed(n);
  5523. }
  5524. }
  5525. else
  5526. {
  5527. if (this.IsNumber(data))
  5528. result=data.toFixed(n);
  5529. }
  5530. return result;
  5531. }
  5532. this.ZTPRICE = function (data, rate)
  5533. {
  5534. if (!this.IsNumber(rate)) return null;
  5535. if (Array.isArray(data))
  5536. {
  5537. var result = [];
  5538. for (var i in data)
  5539. {
  5540. var item = data[i];
  5541. if (this.IsNumber(item)) result[i] = (1 + rate) * item;
  5542. else result[i] = null;
  5543. }
  5544. return result;
  5545. }
  5546. else if (this.IsNumber(data))
  5547. {
  5548. var result = (1 + rate) * data;
  5549. return result;
  5550. }
  5551. }
  5552. this.DTPRICE = function (data, rate)
  5553. {
  5554. if (!this.IsNumber(rate)) return null;
  5555. if (Array.isArray(data))
  5556. {
  5557. var result = [];
  5558. for (var i in data)
  5559. {
  5560. var item = data[i];
  5561. if (this.IsNumber(item)) result[i] = (1 - rate) * item;
  5562. else result[i] = null;
  5563. }
  5564. return result;
  5565. }
  5566. else if (this.IsNumber(data))
  5567. {
  5568. var result = (1 - rate) * data;
  5569. return result;
  5570. }
  5571. }
  5572. /*
  5573. FRACPART(A) 取得小数部分
  5574. 含义:FRACPART(A)返回数值的小数部分
  5575. 阐释:例如FRACPART(12.3)求得0.3,FRACPART(-3.5)求得-0.5
  5576. */
  5577. this.FRACPART = function (data)
  5578. {
  5579. if (Array.isArray(data))
  5580. {
  5581. var result = [];
  5582. var integer = 0;
  5583. for (var i in data)
  5584. {
  5585. var item = data[i];
  5586. if (this.IsNumber(item))
  5587. {
  5588. integer = parseInt(item);
  5589. result[i] = item - integer;
  5590. }
  5591. else result[i] = null;
  5592. }
  5593. return result;
  5594. }
  5595. else if (this.IsNumber(data))
  5596. {
  5597. integer = parseInt(data);
  5598. var result = data - integer;
  5599. return result;
  5600. }
  5601. }
  5602. /*
  5603. 取符号.
  5604. 用法:
  5605. SIGN(X),返回X的符号.当X>0,X=0,X<0分别返回1,0,-1
  5606. */
  5607. this.SIGN=function(data)
  5608. {
  5609. if (Array.isArray(data))
  5610. {
  5611. var result=[];
  5612. for(var i=0;i<data.length;++i)
  5613. {
  5614. var item=data[i];
  5615. result[i]=null;
  5616. if (!IFrameSplitOperator.IsNumber(item)) continue;
  5617. if (item>0) result[i]=1;
  5618. else if (item==0) result[i]=0;
  5619. else result[i]=-1;
  5620. }
  5621. return result;
  5622. }
  5623. else
  5624. {
  5625. if (data>0) return 1;
  5626. else if (data==0) return 0;
  5627. else return -1;
  5628. }
  5629. }
  5630. /*
  5631. 统计连续满足条件的周期数.
  5632. 用法: BARSLASTCOUNT(X),统计连续满足X条件的周期数.
  5633. 例如: BARSLASTCOUNT(CLOSE>OPEN)表示统计连续收阳的周期数
  5634. */
  5635. this.BARSLASTCOUNT=function(data)
  5636. {
  5637. var result=null;
  5638. if (Array.isArray(data))
  5639. {
  5640. result=[];
  5641. if (data.length>0)
  5642. {
  5643. var count=0;
  5644. for(var i=data.length-1;i>=0;--i)
  5645. {
  5646. count=0;
  5647. for(var j=i;j>=0;--j)
  5648. {
  5649. if (data[j]) ++count;
  5650. else break;
  5651. }
  5652. result[i]=count;
  5653. }
  5654. }
  5655. }
  5656. else
  5657. {
  5658. if (data) result=1;
  5659. else result=0;
  5660. }
  5661. return result;
  5662. }
  5663. //取整.
  5664. //用法: INTPART(A)返回沿A绝对值减小方向最接近的整数
  5665. //例如:INTPART(12.3)求得12,INTPART(-3.5)求得-3
  5666. this.INTPART=function(data)
  5667. {
  5668. var result=null;
  5669. if (Array.isArray(data))
  5670. {
  5671. result=[];
  5672. for(var i in data)
  5673. {
  5674. var item=data[i];
  5675. if (this.IsNumber(item)) result[i]=parseInt(item);
  5676. else result[i]=null;
  5677. }
  5678. }
  5679. else if (this.IsNumber(data))
  5680. {
  5681. result=parseInt(data);
  5682. }
  5683. return result;
  5684. }
  5685. //用法:CONST(A),取A最后的值为常量.
  5686. //例如:CONST(INDEXC),表示取大盘现价
  5687. this.CONST=function(data)
  5688. {
  5689. if (Array.isArray(data))
  5690. {
  5691. var count=data.length;
  5692. if (count>0) return data[count-1];
  5693. return null;
  5694. }
  5695. else
  5696. {
  5697. return data;
  5698. }
  5699. }
  5700. //当前值是近多少周期内的最大值.
  5701. //用法: TOPRANGE(X):X是近多少周期内X的最大值
  5702. //例如: TOPRANGE(HIGH)表示当前最高价是近多少周期内最高价的最大值
  5703. this.TOPRANGE=function(data)
  5704. {
  5705. if (this.IsNumber(data)) return 0;
  5706. var result=[];
  5707. if (Array.isArray(data))
  5708. {
  5709. var count=data.length;
  5710. for(var i=count-1; i>=0;--i)
  5711. {
  5712. result[i]=0;
  5713. var item=data[i];
  5714. if (!this.IsNumber(item)) continue;
  5715. var value=0;
  5716. for(var j=i-1;j>=0;--j)
  5717. {
  5718. if (data[j]>item)
  5719. {
  5720. break;
  5721. }
  5722. ++value;
  5723. }
  5724. result[i]=value;
  5725. }
  5726. }
  5727. return result;
  5728. }
  5729. //当前值是近多少周期内的最小值.
  5730. //用法:LOWRANGE(X):X是近多少周期内X的最小值
  5731. //例如:LOWRANGE(LOW)表示当前最低价是近多少周期内最低价的最小值
  5732. this.LOWRANGE=function(data)
  5733. {
  5734. if (this.IsNumber(data)) return 0;
  5735. var result=[];
  5736. if (Array.isArray(data))
  5737. {
  5738. var count=data.length;
  5739. for(var i=count-1; i>=0;--i)
  5740. {
  5741. result[i]=0;
  5742. var item=data[i];
  5743. if (!this.IsNumber(item)) continue;
  5744. var value=0;
  5745. for(var j=i-1;j>=0;--j)
  5746. {
  5747. if (data[j]<item)
  5748. {
  5749. break;
  5750. }
  5751. ++value;
  5752. }
  5753. result[i]=value;
  5754. }
  5755. }
  5756. return result;
  5757. }
  5758. //N周期前的M周期内的第T个最小值.
  5759. //用法:FINDLOW(VAR,N,M,T):VAR在N日前的M天内第T个最低价
  5760. this.FINDLOW=function(data,n,m,t)
  5761. {
  5762. if (this.IsNumber(data)) return data;
  5763. var result=[];
  5764. if (Array.isArray(data))
  5765. {
  5766. var count=data.length;
  5767. for(var i=count-1;i>=0;--i)
  5768. {
  5769. result[i]=null;
  5770. var aryValue=[];
  5771. for(var j=n;j<m;++j)
  5772. {
  5773. var index=i-j;
  5774. if (index<0) break;
  5775. var item=data[index];
  5776. if (this.IsNumber(item)) aryValue.push(item);
  5777. }
  5778. if (aryValue.length>0)
  5779. {
  5780. aryValue.sort(function(a,b) { return a-b;});
  5781. var index=t-1;
  5782. if (index<0) index=0;
  5783. else if (index>=aryValue.length) index=aryValue.length-1;
  5784. result[i]=aryValue[index];
  5785. }
  5786. }
  5787. }
  5788. return result;
  5789. }
  5790. //N周期前的M周期内的第T个最大值.
  5791. //用法:FINDHIGH(VAR,N,M,T):VAR在N日前的M天内第T个最高价
  5792. this.FINDHIGH=function(data,n,m,t)
  5793. {
  5794. if (this.IsNumber(data)) return data;
  5795. var result=[];
  5796. if (Array.isArray(data))
  5797. {
  5798. var count=data.length;
  5799. for(var i=count-1;i>=0;--i)
  5800. {
  5801. result[i]=null;
  5802. var aryValue=[];
  5803. for(var j=n;j<m;++j)
  5804. {
  5805. var index=i-j;
  5806. if (index<0) break;
  5807. var item=data[index];
  5808. if (this.IsNumber(item)) aryValue.push(item);
  5809. }
  5810. if (aryValue.length>0)
  5811. {
  5812. aryValue.sort(function(a,b) { return b-a;});
  5813. var index=t-1;
  5814. if (index<0) index=0;
  5815. else if (index>=aryValue.length) index=aryValue.length-1;
  5816. result[i]=aryValue[index];
  5817. }
  5818. }
  5819. }
  5820. return result;
  5821. }
  5822. //N周期前的M周期内的第T个最大值到当前周期的周期数.
  5823. //用法:FINDHIGHBARS(VAR,N,M,T):VAR在N日前的M天内第T个最高价到当前周期的周期数
  5824. this.FINDHIGHBARS=function(data, n, m, t)
  5825. {
  5826. if (this.IsNumber(data)) return (m-n-t);
  5827. var result=[];
  5828. if (Array.isArray(data))
  5829. {
  5830. var count=data.length;
  5831. for(var i=count-1;i>=0;--i)
  5832. {
  5833. result[i]=null;
  5834. var aryValue=[];
  5835. for(var j=n;j<m;++j)
  5836. {
  5837. var index=i-j;
  5838. if (index<0) break;
  5839. var item=data[index];
  5840. if (this.IsNumber(item)) aryValue.push({ Value:item, Period:j });
  5841. }
  5842. if (aryValue.length>0)
  5843. {
  5844. aryValue.sort(function(a,b) { return b.Value-a.Value;});
  5845. var index=t-1;
  5846. if (index<0) index=0;
  5847. else if (index>=aryValue.length) index=aryValue.length-1;
  5848. result[i]=aryValue[index].Period;
  5849. }
  5850. }
  5851. }
  5852. return result;
  5853. }
  5854. //N周期前的M周期内的第T个最小值到当前周期的周期数.
  5855. //用法:FINDLOWBARS(VAR,N,M,T):VAR在N日前的M天内第T个最低价到当前周期的周期数.
  5856. this.FINDLOWBARS=function(data, n, m, t)
  5857. {
  5858. if (this.IsNumber(data)) return (m-n-t);
  5859. var result=[];
  5860. if (Array.isArray(data))
  5861. {
  5862. var count=data.length;
  5863. for(var i=count-1;i>=0;--i)
  5864. {
  5865. result[i]=null;
  5866. var aryValue=[];
  5867. for(var j=n;j<m;++j)
  5868. {
  5869. var index=i-j;
  5870. if (index<0) break;
  5871. var item=data[index];
  5872. if (this.IsNumber(item)) aryValue.push({ Value:item, Period:j });
  5873. }
  5874. if (aryValue.length>0)
  5875. {
  5876. aryValue.sort(function(a,b) { return a.Value-b.Value;});
  5877. var index=t-1;
  5878. if (index<0) index=0;
  5879. else if (index>=aryValue.length) index=aryValue.length-1;
  5880. result[i]=aryValue[index].Period;
  5881. }
  5882. }
  5883. }
  5884. return result;
  5885. }
  5886. //求高值名次.
  5887. //用法:HOD(X,N):求当前X数据是N周期内的第几个高值,N=0则从第一个有效值开始.
  5888. //例如:HOD(HIGH,20)返回是20日的第几个高价
  5889. this.HOD=function(data, n)
  5890. {
  5891. var result=[];
  5892. if (IFrameSplitOperator.IsNumber(data)) return 1;
  5893. if (Array.isArray(data))
  5894. {
  5895. var count=data.length;
  5896. for(var i=count-1;i>=0;--i)
  5897. {
  5898. var value=data[i];
  5899. if (!IFrameSplitOperator.IsNumber(value)) continue;
  5900. if (Array.isArray(n)) var subCount=parseInt(n[i]);
  5901. else var subCount=parseInt(n);
  5902. if (n<=0) subCount=i;
  5903. var index=1;
  5904. for(var j=i-1, k=1; j>=0 && k<subCount; --j, ++k)
  5905. {
  5906. var item=data[j];
  5907. if (IFrameSplitOperator.IsNumber(item) && item>value) ++index;
  5908. }
  5909. result[i]=index;
  5910. }
  5911. }
  5912. return result;
  5913. }
  5914. //求低值名次.
  5915. //用法:LOD(X,N):求当前X数据是N周期内的第几个低值,N=0则从第一个有效值开始.
  5916. //例如:LOD(LOW,20)返回是20日的第几个低价
  5917. this.LOD=function(data, n)
  5918. {
  5919. var result=[];
  5920. if (IFrameSplitOperator.IsNumber(data)) return 1;
  5921. if (Array.isArray(data))
  5922. {
  5923. var count=data.length;
  5924. for(var i=count-1;i>=0;--i)
  5925. {
  5926. var value=data[i];
  5927. if (!IFrameSplitOperator.IsNumber(value)) continue;
  5928. if (Array.isArray(n)) var subCount=parseInt(n[i]);
  5929. else var subCount=parseInt(n);
  5930. if (n<=0) subCount=i;
  5931. var index=1;
  5932. for(var j=i-1, k=1; j>=0 && k<subCount; --j, ++k)
  5933. {
  5934. var item=data[j];
  5935. if (IFrameSplitOperator.IsNumber(item) && item<value) ++index;
  5936. }
  5937. result[i]=index;
  5938. }
  5939. }
  5940. return result;
  5941. }
  5942. //属于未来函数,下一次条件成立到当前的周期数.
  5943. //用法:BARSNEXT(X):下一次X不为0到现在的天数
  5944. //例如:BARSNEXT(CLOSE/REF(CLOSE,1)>=1.1)表示下一个涨停板到当前的周期数
  5945. this.BARSNEXT=function(data)
  5946. {
  5947. if (!Array.isArray(data)) return 0;
  5948. var result=[];
  5949. for(var i=0;i<data.length;++i)
  5950. {
  5951. result[i]=0;
  5952. for(var j=i, k=0;j<data.length;++j, ++k)
  5953. {
  5954. var item=data[j];
  5955. if (item>0)
  5956. {
  5957. result[i]=k;
  5958. break;
  5959. }
  5960. }
  5961. }
  5962. return result;
  5963. }
  5964. //取随机数.
  5965. //用法:RAND(N),返回一个范围在1-N的随机整数
  5966. this.RAND=function(n)
  5967. {
  5968. if (Array.isArray(n))
  5969. {
  5970. var result=[];
  5971. for(var i in n)
  5972. {
  5973. result[i]=null;
  5974. var item=n[i];
  5975. var value=parseInt(item);
  5976. if (value<=0) continue;
  5977. result[i]=Math.ceil(Math.random()*value);
  5978. }
  5979. return result;
  5980. }
  5981. else
  5982. {
  5983. var value=parseInt(n);
  5984. if (value<=0) return null;
  5985. var stockData= this.SymbolData.Data;
  5986. var count=stockData.Data.length;
  5987. var result=[];
  5988. for(var i=0;i<count;++i)
  5989. {
  5990. result[i]=Math.ceil(Math.random()*value);
  5991. }
  5992. return result;
  5993. }
  5994. }
  5995. //求自适应均线值.
  5996. //用法:AMA(X,A),A为自适应系数,必须小于1.
  5997. //算法:Y=Y'+A*(X-Y').初值为X
  5998. this.AMA=function(data,n)
  5999. {
  6000. var result=[];
  6001. var period;
  6002. if (Array.isArray(n))
  6003. {
  6004. //取最新的一个数据做为自适应系数
  6005. for(var i=data.length-1;i>=0;--i)
  6006. {
  6007. if (this.IsNumber(n[i]))
  6008. {
  6009. period=n[i];
  6010. break;
  6011. }
  6012. }
  6013. }
  6014. else
  6015. {
  6016. period=n;
  6017. }
  6018. if (this.IsNumber(period))
  6019. {
  6020. if (period>1) return result;
  6021. var index=0;
  6022. var value=0;
  6023. for(index;index<data.length;++index)
  6024. {
  6025. result[index]=null;
  6026. if (this.IsNumber(data[index]))
  6027. {
  6028. value=data[index];
  6029. result[index]=value;
  6030. break;
  6031. }
  6032. }
  6033. for(var i=index+1;i<data.length;++i)
  6034. {
  6035. var item=data[i];
  6036. result[i]=result[i-1]+period*(item-result[i-1]);
  6037. }
  6038. }
  6039. return result;
  6040. }
  6041. //返回移动平均
  6042. //用法:TMA(X,A,B),A和B必须小于1,算法 Y=(A*Y'+B*X),其中Y'表示上一周期Y值.初值为X
  6043. this.TMA=function(data, a, b)
  6044. {
  6045. var result=[];
  6046. if (this.IsNumber(a) && a<=1 && this.IsNumber(b) && b<1)
  6047. {
  6048. var bFirstFind=false;
  6049. var proValue; //上一个值
  6050. for(var i in data)
  6051. {
  6052. result[i]=null;
  6053. if (bFirstFind==false)
  6054. {
  6055. var item=data[i];
  6056. if (this.IsNumber(item))
  6057. {
  6058. result[i]=item;
  6059. proValue=result[i];
  6060. bFirstFind=true;
  6061. }
  6062. }
  6063. else
  6064. {
  6065. var item=data[i];
  6066. if (!this.IsNumber(item)) continue;
  6067. result[i]=a*result[i-1]+b*item;
  6068. proValue=result[i];
  6069. }
  6070. }
  6071. }
  6072. return result;
  6073. }
  6074. this.ROUND=function(data)
  6075. {
  6076. if (this.IsNumber(data))
  6077. {
  6078. return Math.round(data);
  6079. }
  6080. var result=[];
  6081. if (Array.isArray(data))
  6082. {
  6083. for(var i in data)
  6084. {
  6085. var item=data[i];
  6086. if (this.IsNumber(item))
  6087. result[i]=Math.round(item);
  6088. else
  6089. result[i]=null;
  6090. }
  6091. }
  6092. return result;
  6093. }
  6094. this.ROUND2=function(data,n)
  6095. {
  6096. var ROUND2_SEED=
  6097. [
  6098. 1,10,100,1000,
  6099. 10000,
  6100. 100000,
  6101. 1000000,
  6102. 10000000,
  6103. 100000000,
  6104. 1000000000,
  6105. 10000000000,
  6106. 100000000000,
  6107. 1000000000000
  6108. ];
  6109. var decimal=0;
  6110. if (this.IsNumber(n)) decimal=parseInt(n);
  6111. if (n<0) decimal=0;
  6112. else if (n>=ROUND2_SEED.length) decimal=ROUND2_SEED.length-1;
  6113. if (this.IsNumber(data))
  6114. {
  6115. return Math.round(data*ROUND2_SEED[decimal])/ROUND2_SEED[decimal];
  6116. }
  6117. var result=[];
  6118. if (Array.isArray(data))
  6119. {
  6120. for(var i in data)
  6121. {
  6122. var item=data[i];
  6123. if (this.IsNumber(item))
  6124. {
  6125. result[i]=Math.round(item*ROUND2_SEED[decimal])/ROUND2_SEED[decimal];
  6126. }
  6127. else
  6128. {
  6129. result[i]=null;
  6130. }
  6131. }
  6132. }
  6133. return result;
  6134. }
  6135. /*
  6136. TRMA(X,N) 求X在N个周期的三角移动平均值
  6137. 算法三角移动平均线公式是采用算数移动平均并且对第一个移动平均线再一次应用算数移动平均
  6138. TRMA(X,N) 算法如下
  6139. ma_half= MA(X,N/2)
  6140. trma=MA(ma_half,N/2)
  6141. 1N包含当前k线
  6142. 2当N为有效值但当前的k线数不足N根函数返回空值
  6143. 3N为0或空值的情况下函数返回空值
  6144. 例1
  6145. TRMA5:TRMA(CLOSE,5);//计算5个周期内收盘价的三角移动平均。(N不能被2整除)
  6146. //TRMA(CLOSE,5)=MA(MA(CLOSE,(5+1)/2)),(5+1)/2);
  6147. 例2:
  6148. TRMA10:TRMA(CLOSE,10);// 计算10个周期内收盘价的三角移动平均。(N能被2整除)
  6149. TRMA(CLOSE,10)=MA(MA(CLOSE,10/2),(10/2)+1));
  6150. */
  6151. this.TRMA=function(data,n)
  6152. {
  6153. if (!this.IsNumber(n) || n<=0) return [];
  6154. n=parseInt(n);
  6155. var nFalf=0,nFalf2=0;
  6156. if (n%2==0)
  6157. {
  6158. nFalf=parseInt(n/2);
  6159. nFalf2=nFalf+1;
  6160. }
  6161. else
  6162. {
  6163. nFalf=parseInt((n+1)/2);
  6164. nFalf2=nFalf;
  6165. }
  6166. var maFalf=this.MA(data,nFalf);
  6167. var result=this.MA(maFalf,nFalf2);
  6168. return result;
  6169. }
  6170. //VALUEWHEN(COND,X)
  6171. //当COND条件成立时,取X的当前值,否则取VALUEWHEN的上个值.
  6172. this.VALUEWHEN=function(cond,data)
  6173. {
  6174. if (Array.isArray(cond))
  6175. {
  6176. var result=[];
  6177. if (Array.isArray(data))
  6178. {
  6179. var preValue=null;
  6180. for(var i in cond)
  6181. {
  6182. if (i>=data.length)
  6183. {
  6184. result[i]=preValue;
  6185. continue;
  6186. }
  6187. var item=data[i];
  6188. if (cond[i])
  6189. {
  6190. result[i]=item;
  6191. preValue=item;
  6192. }
  6193. else
  6194. {
  6195. result[i]=preValue;
  6196. }
  6197. }
  6198. }
  6199. else
  6200. {
  6201. var preValue=null;
  6202. for(var i in cond)
  6203. {
  6204. if (cond[i])
  6205. {
  6206. result[i]=data;
  6207. preValue=data;
  6208. }
  6209. else
  6210. {
  6211. result[i]=preValue;
  6212. }
  6213. }
  6214. }
  6215. return result;
  6216. }
  6217. else
  6218. {
  6219. return cond? 1:0;
  6220. }
  6221. }
  6222. /*
  6223. HARMEAN(X,N) 求X在N个周期内的调和平均值
  6224. 算法举例HARMEAN(X,5)=1/[(1/X1+1/X2+1/X3+1/X4+1/X5)/5]
  6225. 1N包含当前k线
  6226. 2调和平均值与倒数的简单平均值互为倒数
  6227. 3当N为有效值但当前的k线数不足N根函数返回空值
  6228. 4N为0或空值的情况下函数返回空值
  6229. 5X为0或空值的情况下函数返回空值
  6230. 6N可以为变量
  6231. HM5:=HARMEAN(C,5);//求5周期收盘价的调和平均值。
  6232. */
  6233. this.HARMEAN=function(data, n)
  6234. {
  6235. var result=[];
  6236. if (Array.isArray(data))
  6237. {
  6238. if (Array.isArray(n))
  6239. {
  6240. for(var i=0;i<data.length;++i)
  6241. {
  6242. if (i>=n.length)
  6243. {
  6244. result[i]=null;
  6245. continue;
  6246. }
  6247. var count=parseInt(n[i]);
  6248. if (count<=0 || count>i)
  6249. {
  6250. result[i]=null;
  6251. continue;
  6252. }
  6253. var sum=0;
  6254. for(var j=0;j<count;++j)
  6255. {
  6256. var item=data[i-j];
  6257. if (!this.IsNumber(item) || item==0)
  6258. {
  6259. sum=null;
  6260. break;
  6261. }
  6262. sum+=1/item;
  6263. }
  6264. if (sum==null)
  6265. {
  6266. result[i]=null;
  6267. }
  6268. else
  6269. {
  6270. result[i]=1/(sum/count);
  6271. }
  6272. }
  6273. }
  6274. else if (this.IsNumber(n))
  6275. {
  6276. n=parseInt(n);
  6277. if (n<=0) return result;
  6278. for(var i=0;i<data.length;++i)
  6279. {
  6280. if (n>i)
  6281. {
  6282. result[i]=null;
  6283. continue;
  6284. }
  6285. var sum=0;
  6286. for(var j=0;j<n;++j)
  6287. {
  6288. var item=data[i-j];
  6289. if (!this.IsNumber(item) || item==0)
  6290. {
  6291. sum=null;
  6292. break;
  6293. }
  6294. sum+=1/item;
  6295. }
  6296. if (sum==null)
  6297. {
  6298. result[i]=null;
  6299. }
  6300. else
  6301. {
  6302. result[i]=1/(sum/n);
  6303. }
  6304. }
  6305. }
  6306. }
  6307. return result;
  6308. }
  6309. //指定日期到1990.12.19的天数.
  6310. //用法: DATETODAY(date)
  6311. //DATETODAY(date).返回date到1990.12.19的天数.有效日期为(901219-1341231)
  6312. //例如: DATETODAY(901219)返回0.
  6313. this.DATETODAY=function(data)
  6314. {
  6315. var result=[];
  6316. var startDate=new Date('1990-12-19')
  6317. var startValue=19901219;
  6318. var ONE_DAY=1000 * 60 * 60 * 24
  6319. if (Array.isArray(data))
  6320. {
  6321. for(var i in data)
  6322. {
  6323. result[i]=null;
  6324. var item=data[i];
  6325. if (!this.IsNumber(item)) continue;
  6326. var value=item+19000000;
  6327. if (value<startValue) continue;
  6328. var year=parseInt(value/10000);
  6329. var month=parseInt((value%10000)/100);
  6330. var day=parseInt(value%100);
  6331. var dateItem=new Date(`${year}-${month}-${day}`);
  6332. result[i]=Math.round((dateItem-startDate)/ONE_DAY);
  6333. }
  6334. }
  6335. else if (this.IsNumber(data))
  6336. {
  6337. var value=data+19000000;
  6338. if (value>=startValue)
  6339. {
  6340. var year=parseInt(value/10000);
  6341. var month=parseInt((value%10000)/100);
  6342. var day=parseInt(value%100);
  6343. var dateItem=new Date(`${year}-${month}-${day}`);
  6344. return Math.round((dateItem-dateItem)/ONE_DAY);
  6345. }
  6346. }
  6347. return result;
  6348. }
  6349. //求1990.12.19后第若干天的日期.
  6350. //用法:DAYTODATE(N)
  6351. //DAYTODATE(N).返回1990.12.19后第N天的日期.有效天数为(0-20000)
  6352. //例如:DAYTODATE(0)返回901219.
  6353. this.DAYTODATE=function(data)
  6354. {
  6355. var startDate=new Date('1990-12-19')
  6356. var result=[];
  6357. if (Array.isArray(data))
  6358. {
  6359. for(var i in data)
  6360. {
  6361. result[i]=null;
  6362. var item=data[i];
  6363. if (!this.IsNumber(item)) continue;
  6364. startDate.setDate(startDate.getDate()+item);
  6365. var value=startDate.getFullYear()*10000+(startDate.getMonth()+1)*100+startDate.getDate();
  6366. value-=19000000;
  6367. result[i]=value;
  6368. startDate.setDate(startDate.getDate()-item);
  6369. }
  6370. }
  6371. else if (this.IsNumber(data))
  6372. {
  6373. startDate.setDate(startDate.getDate()+data);
  6374. var value=startDate.getFullYear()*10000+(startDate.getMonth()+1)*100+startDate.getDate();
  6375. value-=19000000;
  6376. return value;
  6377. }
  6378. return result;
  6379. }
  6380. /*
  6381. 求指定时刻距0时有多长时间.
  6382. 用法:
  6383. TIMETOSEC(time)
  6384. TIMETOSEC(time).返回time时刻距0时有多长时间,单位为秒.有效时间为(0-235959)
  6385. 例如:
  6386. TIMETOSEC(93000)返回34200.
  6387. */
  6388. this.TIMETOSEC=function(time)
  6389. {
  6390. var hour=parseInt(time/10000);
  6391. var minute=parseInt((time%10000)/100);
  6392. var sec=time%100;
  6393. var value=hour*60*60+minute*60+sec;
  6394. return value;
  6395. }
  6396. /*
  6397. 求0时后若干秒是什么时间.
  6398. 用法:
  6399. SECTOTIME(N)
  6400. SECTOTIME(N).返回0时后N秒是什么时间.有效秒数为(0-86399)
  6401. 例如:
  6402. SECTOTIME(34200)返回93000.
  6403. */
  6404. this.SECTOTIME=function(data)
  6405. {
  6406. var daySec = 24 * 60 * 60;
  6407. var hourSec= 60 * 60;
  6408. var minuteSec=60;
  6409. var dd = Math.floor(data / daySec);
  6410. var hh = Math.floor((data % daySec) / hourSec);
  6411. var mm = Math.floor((data % hourSec) / minuteSec);
  6412. var ss=data%minuteSec;
  6413. var value=hh*10000+mm*100+ss;
  6414. return value;
  6415. }
  6416. this.MOD=function(data, data2)
  6417. {
  6418. var result=[];
  6419. let isNumber=typeof(data)=='number';
  6420. let isNumber2=typeof(data2)=='number';
  6421. //单数值
  6422. if (isNumber && isNumber2)
  6423. {
  6424. return JSAlgorithm.MOD(data,data2);
  6425. }
  6426. else if (!isNumber && !isNumber2) //都是数组相加
  6427. {
  6428. let count=Math.max(data.length, data2.length);
  6429. for(let i=0;i<count;++i)
  6430. {
  6431. result[i]=null; //初始化
  6432. if (i<data.length && i<data2.length)
  6433. {
  6434. if ( this.IsNumber(data[i]) && this.IsNumber(data2[i]) ) result[i]=JSAlgorithm.MOD(data[i],data2[i]);
  6435. }
  6436. }
  6437. return result;
  6438. }
  6439. else if (isNumber && !isNumber2) //单数字 数组
  6440. {
  6441. for(var i in data2)
  6442. {
  6443. result[i]=null;
  6444. if (this.IsNumber(data) && this.IsNumber(data2[i])) result[i]=JSAlgorithm.MOD(data,data2[i]);
  6445. }
  6446. return result;
  6447. }
  6448. else if (!isNumber && isNumber2) //数组 单数字
  6449. {
  6450. for(var i in data)
  6451. {
  6452. result[i]=null;
  6453. if (this.IsNumber(data[i]) && this.IsNumber(data2)) result[i]=JSAlgorithm.MOD(data[i],data2);
  6454. }
  6455. return result;
  6456. }
  6457. return result;
  6458. }
  6459. this.POW=function(data, n)
  6460. {
  6461. var result=[];
  6462. if (Array.isArray(data) && Array.isArray(n))
  6463. {
  6464. for(var i=0;i<data.length;++i)
  6465. {
  6466. var value=data[i];
  6467. var value2=n[i];
  6468. if (this.IsNumber(value) && this.IsNumber(value2)) result[i]=Math.pow(value,value2);
  6469. else result[i]=null;
  6470. }
  6471. }
  6472. else if (this.IsNumber(data) && Array.isArray(n))
  6473. {
  6474. for(var i=0;i<n.length;++i)
  6475. {
  6476. var item=n[i];
  6477. if (this.IsNumber(item)) result[i]=Math.pow(data,item);
  6478. else result[i]=null;
  6479. }
  6480. }
  6481. else if (this.IsNumber(data) && this.IsNumber(n))
  6482. {
  6483. return Math.pow(data,n);
  6484. }
  6485. else if (Array.isArray(data) && this.IsNumber(n))
  6486. {
  6487. for(var i=0; i<data.length;++i)
  6488. {
  6489. var item=data[i];
  6490. if (this.IsNumber(item)) result[i]=Math.pow(item,n);
  6491. else result[i]=null;
  6492. }
  6493. }
  6494. return result;
  6495. }
  6496. this.CEILING=function(data)
  6497. {
  6498. let isNumber=typeof(data)=='number';
  6499. if (isNumber) return parseInt(data);
  6500. var result=[];
  6501. for(var i in data)
  6502. {
  6503. var item=data[i];
  6504. if (this.IsNumber(item)) result[i]=parseInt(item);
  6505. else result[i]=null;
  6506. }
  6507. return result;
  6508. }
  6509. this.FLOOR=function(data)
  6510. {
  6511. let isNumber=typeof(data)=='number';
  6512. if (isNumber) return parseInt((data-1));
  6513. var result=[];
  6514. for(var i in data)
  6515. {
  6516. var item=data[i];
  6517. if (this.IsNumber(item)) result[i]=parseInt((item-1));
  6518. else result[i]=null;
  6519. }
  6520. return result;
  6521. }
  6522. this.PWINNER=function(n, data, node)
  6523. {
  6524. var result=[];
  6525. return result;
  6526. }
  6527. //用法:ANY(CLOSE>OPEN,10),表示前10日内存在着阳线
  6528. this.ANY=function(data, n)
  6529. {
  6530. if (n<=0) n=1;
  6531. var result=[];
  6532. if (Array.isArray(data))
  6533. {
  6534. if (n>=data.length) return 0;
  6535. for(var i=n, j=0;i<data.length;++i)
  6536. {
  6537. var value=0;
  6538. for(j=0;j<n;++j)
  6539. {
  6540. var item=data[i-j];
  6541. if (item>0)
  6542. {
  6543. value=1;
  6544. break;
  6545. }
  6546. }
  6547. result[i]=value;
  6548. }
  6549. return result;
  6550. }
  6551. else if (IFrameSplitOperator.IsNumber(data))
  6552. {
  6553. if (data<=0) return 0;
  6554. if (n>=this.SymbolData.Data.Data.length) return 0;
  6555. for(var i=n; i<this.SymbolData.Data.Data.length; ++i)
  6556. {
  6557. result[i]=1;
  6558. }
  6559. return result;
  6560. }
  6561. else
  6562. {
  6563. return 0;
  6564. }
  6565. }
  6566. //用法:ALL(CLOSE>OPEN,10),表示前10日内一直阳线
  6567. this.ALL=function(data, n)
  6568. {
  6569. if (n<=0) n=1;
  6570. var result=[];
  6571. if (Array.isArray(data))
  6572. {
  6573. if (n>=data.length) return 0;
  6574. for(var i=n, j=0;i<data.length;++i)
  6575. {
  6576. var value=1;
  6577. for(j=0;j<n;++j)
  6578. {
  6579. var item=data[i-j];
  6580. if (!(item>0))
  6581. {
  6582. value=0;
  6583. break;
  6584. }
  6585. }
  6586. result[i]=value;
  6587. }
  6588. return result;
  6589. }
  6590. else if (IFrameSplitOperator.IsNumber(data))
  6591. {
  6592. if (data<=0) return 0;
  6593. if (n>=this.SymbolData.Data.Data.length) return 0;
  6594. for(var i=n; i<this.SymbolData.Data.Data.length; ++i)
  6595. {
  6596. result[i]=1;
  6597. }
  6598. return result;
  6599. }
  6600. else
  6601. {
  6602. return 0;
  6603. }
  6604. }
  6605. /*
  6606. TESTSKIP(A):满足A则直接返回.
  6607. 用法:
  6608. TESTSKIP(A)
  6609. 表示如果满足条件A则该公式直接返回,不再计算接下来的表达式 注意:A为非序列数据,只取最后一个数据
  6610. */
  6611. this.TESTSKIP=function(data, node)
  6612. {
  6613. if (Array.isArray(data))
  6614. {
  6615. if (data.length<=0) return false;
  6616. var item=data[data.length-1];
  6617. if (!item) return false;
  6618. return true;
  6619. }
  6620. else if (IFrameSplitOperator.IsNumber(data))
  6621. {
  6622. if (data<=0) return false;
  6623. return true;
  6624. }
  6625. else
  6626. {
  6627. if (!data) return false;
  6628. return true;
  6629. }
  6630. }
  6631. /*,().
  6632. 用法:
  6633. IFC(X,A,B)若X不为0则执行A,否则执行B.IFC与IF函数的区别:根据X的值来选择性执行AB表达式.
  6634. 例如:
  6635. IFC(CLOSE>OPEN,HIGH,TESTSKIP(1));L;表示当日收阳则返回最高值,并执行下一句"L;",否则退出公式计算
  6636. */
  6637. this.IFC=function(data)
  6638. {
  6639. if (Array.isArray(data))
  6640. {
  6641. var item=data[data.length-1];
  6642. if (IFrameSplitOperator.IsNumber(item)) return item>0;
  6643. return false;
  6644. }
  6645. else if (IFrameSplitOperator.IsNumber(data))
  6646. {
  6647. return data>0;
  6648. }
  6649. else
  6650. {
  6651. return false;
  6652. }
  6653. }
  6654. /*
  6655. 有效数据右对齐.
  6656. 用法:
  6657. ALIGNRIGHT(X)有效数据向右移动,左边空出来的周期填充无效值
  6658. 例如:TC:=IF(CURRBARSCOUNT=2 || CURRBARSCOUNT=5,DRAWNULL,C);XC:ALIGNRIGHT(TC);删除了两天的收盘价,并将剩余数据右移
  6659. */
  6660. this.ALIGNRIGHT=function(data)
  6661. {
  6662. if (Array.isArray(data))
  6663. {
  6664. var result=[];
  6665. var index=data.length-1;
  6666. for(var i=data.length-1;i>=0;--i)
  6667. {
  6668. var item=data[i];
  6669. if (IFrameSplitOperator.IsNumber(item) || IFrameSplitOperator.IsString(item))
  6670. {
  6671. result[index]=item;
  6672. --index;
  6673. }
  6674. }
  6675. for(var i=index;i>=0;--i)
  6676. {
  6677. result[i]=null;
  6678. }
  6679. return result;
  6680. }
  6681. else
  6682. {
  6683. return data;
  6684. }
  6685. }
  6686. //格式化字符串 "{0}-{1}", C, O;
  6687. this.STRFORMAT=function(strFormat,args,node)
  6688. {
  6689. var aryParam=strFormat.match(/{\d+}/g);
  6690. if (!IFrameSplitOperator.IsNonEmptyArray(aryParam)) return null;
  6691. var mapParam=new Map(); //key=index, value={Text}
  6692. var maxIndex=-1;
  6693. for(var i=0;i<aryParam.length;++i)
  6694. {
  6695. var item=aryParam[i];
  6696. if (item.length<3) continue;
  6697. var value=item.slice(1, item.length-1);
  6698. var index=parseInt(value);
  6699. var paramItem={ Src:item, Index:index, Text:null};
  6700. if (maxIndex<index) maxIndex=index;
  6701. mapParam.set(index, paramItem);
  6702. }
  6703. var isArray=false; //是否输出数组字符串
  6704. var maxCount=0;
  6705. for(var i=1;i<args.length;++i)
  6706. {
  6707. var item=args[i];
  6708. if (Array.isArray(item))
  6709. {
  6710. isArray=true;
  6711. if (maxCount<item.length) maxCount=item.length;
  6712. }
  6713. }
  6714. if (isArray)
  6715. {
  6716. var result=[];
  6717. for(var i=0;i<maxCount;++i)
  6718. {
  6719. var strItem=strFormat;
  6720. for(var item of mapParam)
  6721. {
  6722. var paramInfo=item[1];
  6723. var paramItem=args[paramInfo.Index+1];
  6724. var text="null";
  6725. if (paramItem)
  6726. {
  6727. if (Array.isArray(paramItem))
  6728. {
  6729. var value=paramItem[i];
  6730. if (value) text=`${value}`;
  6731. }
  6732. else
  6733. {
  6734. text=`${paramItem}`;
  6735. }
  6736. }
  6737. strItem=strItem.replace(paramInfo.Src, text);
  6738. }
  6739. result[i]=strItem;
  6740. }
  6741. return result;
  6742. }
  6743. else
  6744. {
  6745. var result=strFormat;
  6746. for(var item of mapParam)
  6747. {
  6748. var paramInfo=item[1];
  6749. var paramItem=args[paramInfo.Index+1];
  6750. var text="null";
  6751. if (paramItem)
  6752. {
  6753. text=`${paramItem}`;
  6754. }
  6755. result=result.replace(paramInfo.Src, text);
  6756. }
  6757. return result;
  6758. }
  6759. }
  6760. //函数调用
  6761. this.CallFunction=function(name,args,node)
  6762. {
  6763. switch(name)
  6764. {
  6765. case 'MAX':
  6766. case "MAX6":
  6767. return this.MAX(args,node);
  6768. case 'MIN':
  6769. case "MIN6":
  6770. return this.MIN(args,node);
  6771. case 'REF':
  6772. return this.REF(args[0], args[1]);
  6773. case "REFV":
  6774. return this.REFV(args[0], args[1]);
  6775. case 'REFX':
  6776. return this.REFX(args[0], args[1]);
  6777. case "REFXV":
  6778. return this.REFXV(args[0], args[1]);
  6779. case "REFX1": //文华函数
  6780. return this.REFX(args[0], args[1]);
  6781. case 'ABS':
  6782. return this.ABS(args[0]);
  6783. case 'MA':
  6784. return this.MA(args[0], args[1]);
  6785. case "EMA":
  6786. return this.EMA(args[0], args[1]);
  6787. case "SMA":
  6788. return this.SMA(args[0], args[1],args[2]);
  6789. case "DMA":
  6790. return this.DMA(args[0], args[1]);
  6791. case "XMA":
  6792. return this.XMA(args[0], args[1]);
  6793. case 'EXPMA':
  6794. return this.EXPMA(args[0], args[1]);
  6795. case 'EXPMEMA':
  6796. return this.EXPMEMA(args[0], args[1]);
  6797. case 'COUNT':
  6798. return this.COUNT(args[0], args[1]);
  6799. case 'LLV':
  6800. return this.LLV(args[0], args[1]);
  6801. case "LV":
  6802. return this.LV(args[0], args[1]);
  6803. case 'LLVBARS':
  6804. return this.LLVBARS(args[0], args[1]);
  6805. case 'HHV':
  6806. return this.HHV(args[0], args[1]);
  6807. case "HV":
  6808. return this.HV(args[0], args[1]);
  6809. case 'HHVBARS':
  6810. return this.HHVBARS(args[0], args[1]);
  6811. case 'MULAR':
  6812. return this.MULAR(args[0], args[1]);
  6813. case 'CROSS':
  6814. return this.CROSS(args[0], args[1]);
  6815. case "CROSSDOWN":
  6816. return this.CROSSDOWN(args[0], args[1]);
  6817. case 'LONGCROSS':
  6818. return this.LONGCROSS(args[0], args[1], args[2]);
  6819. case 'AVEDEV':
  6820. return this.AVEDEV(args[0], args[1]);
  6821. case 'STD':
  6822. return this.STD(args[0], args[1]);
  6823. case "STDDEV":
  6824. return this.STDDEV(args[0], args[1]);
  6825. case 'IF':
  6826. case 'IFF':
  6827. case "IFELSE":
  6828. return this.IF(args[0], args[1], args[2]);
  6829. case 'IFN':
  6830. return this.IFN(args[0], args[1], args[2]);
  6831. case 'NOT':
  6832. return this.NOT(args[0]);
  6833. case 'SUM':
  6834. return this.SUM(args[0], args[1]);
  6835. case 'RANGE':
  6836. return this.RANGE(args[0],args[1],args[2]);
  6837. case 'EXIST':
  6838. return this.EXIST(args[0],args[1]);
  6839. case 'EXISTR':
  6840. return this.EXISTR(args[0], args[1], args[2]);
  6841. case "ISVALID":
  6842. return this.ISVALID(args[0]);
  6843. case 'FILTER':
  6844. return this.FILTER(args[0], args[1]);
  6845. case 'TFILTER':
  6846. return this.TFILTER(args[0],args[1],args[2]);
  6847. case 'SLOPE':
  6848. return this.SLOPE(args[0],args[1]);
  6849. case 'BARSLAST':
  6850. return this.BARSLAST(args[0]);
  6851. case 'BARSCOUNT':
  6852. return this.BARSCOUNT(args[0]);
  6853. case 'BARSSINCEN':
  6854. return this.BARSSINCEN(args[0], args[1]);
  6855. case 'BARSSINCE':
  6856. return this.BARSSINCE(args[0]);
  6857. case 'LAST':
  6858. return this.LAST(args[0], args[1], args[2]);
  6859. case 'EVERY':
  6860. return this.EVERY(args[0], args[1]);
  6861. case 'ZIG':
  6862. return this.ZIG(args[0], args[1]);
  6863. case 'TROUGHBARS':
  6864. return this.TROUGHBARS(args[0], args[1], args[2]);
  6865. case "TROUGH":
  6866. return this.TROUGH(args[0],args[1],args[2]);
  6867. case 'PEAKBARS':
  6868. return this.PEAKBARS(args[0], args[1], args[2]);
  6869. case 'PEAK':
  6870. return this.PEAK(args[0],args[1],args[2]);
  6871. case 'COST':
  6872. return this.COST(args[0], node);
  6873. case 'WINNER':
  6874. return this.WINNER(args[0], node);
  6875. case "PWINNER":
  6876. return this.PWINNER(args[0],args[1],node);
  6877. case 'UPNDAY':
  6878. return this.UPNDAY(args[0], args[1]);
  6879. case 'DOWNNDAY':
  6880. return this.DOWNNDAY(args[0], args[1]);
  6881. case 'NDAY':
  6882. return this.NDAY(args[0], args[1], args[2]);
  6883. case 'DEVSQ':
  6884. return this.DEVSQ(args[0], args[1]);
  6885. case 'FORCAST':
  6886. return this.FORCAST(args[0], args[1]);
  6887. case 'STDP':
  6888. return this.STDP(args[0], args[1]);
  6889. case 'VAR':
  6890. return this.VAR(args[0], args[1]);
  6891. case 'VARP':
  6892. return this.VARP(args[0], args[1]);
  6893. case 'RELATE':
  6894. return this.RELATE(args[0], args[1], args[2]);
  6895. case 'COVAR':
  6896. return this.COVAR(args[0], args[1], args[2]);
  6897. case 'BETA':
  6898. return this.BETA(args[0]);
  6899. case 'BETA2':
  6900. return this.BETA2(args[0], args[1], args[2]);
  6901. case 'WMA':
  6902. return this.WMA(args[0], args[1]);
  6903. case 'MEMA':
  6904. return this.MEMA(args[0], args[1]);
  6905. case 'SUMBARS':
  6906. return this.SUMBARS(args[0], args[1]);
  6907. case 'REVERSE':
  6908. return this.REVERSE(args[0]);
  6909. case 'SAR':
  6910. return this.SAR(args[0], args[1], args[2]);
  6911. case 'SARTURN':
  6912. return this.SARTURN(args[0], args[1], args[2]);
  6913. case 'BACKSET':
  6914. return this.BACKSET(args[0], args[1]);
  6915. case 'STRCAT':
  6916. return this.STRCAT(args[0], args[1]);
  6917. case "VARCAT":
  6918. return this.VARCAT(args[0], args[1]);
  6919. case "VAR2STR":
  6920. return this.VAR2STR(args[0], args[1]);
  6921. case 'CON2STR':
  6922. return this.CON2STR(args[0], args[1]);
  6923. case "STRSPACE":
  6924. return this.STRSPACE(args[0]);
  6925. case 'FINDSTR':
  6926. return this.FINDSTR(args[0], args[1]);
  6927. case "STRCMP":
  6928. return this.STRCMP(args[0], args[1]);
  6929. case "STRLEN":
  6930. return this.STRLEN(args[0]);
  6931. case "STRFORMAT":
  6932. return this.STRFORMAT(args[0], args, node);
  6933. case 'DTPRICE':
  6934. return this.DTPRICE(args[0], args[1]);
  6935. case 'ZTPRICE':
  6936. return this.ZTPRICE(args[0], args[1]);
  6937. case 'FRACPART':
  6938. return this.FRACPART(args[0]);
  6939. case "SIGN":
  6940. return this.SIGN(args[0]);
  6941. case 'BARSLASTCOUNT':
  6942. return this.BARSLASTCOUNT(args[0]);
  6943. case 'INTPART':
  6944. return this.INTPART(args[0]);
  6945. case "CONST":
  6946. return this.CONST(args[0]);
  6947. case "TOPRANGE":
  6948. return this.TOPRANGE(args[0]);
  6949. case "LOWRANGE":
  6950. return this.LOWRANGE(args[0]);
  6951. case "FINDLOW":
  6952. return this.FINDLOW(args[0],args[1],args[2],args[3]);
  6953. case "FINDLOWBARS":
  6954. return this.FINDLOWBARS(args[0],args[1],args[2],args[3]);
  6955. case "FINDHIGH":
  6956. return this.FINDHIGH(args[0],args[1],args[2],args[3]);
  6957. case "FINDHIGHBARS":
  6958. return this.FINDHIGHBARS(args[0],args[1],args[2],args[3]);
  6959. case "BARSNEXT":
  6960. return this.BARSNEXT(args[0]);
  6961. case "HOD":
  6962. return this.HOD(args[0], args[1]);
  6963. case "LOD":
  6964. return this.LOD(args[0], args[1]);
  6965. case "AMA":
  6966. return this.AMA(args[0], args[1]);
  6967. case "TMA":
  6968. return this.TMA(args[0],args[1],args[2]);
  6969. case "ROUND":
  6970. return this.ROUND(args[0]);
  6971. case "ROUND2":
  6972. return this.ROUND2(args[0],args[1]);
  6973. case "TRMA":
  6974. return this.TRMA(args[0],args[1]);
  6975. case "VALUEWHEN":
  6976. return this.VALUEWHEN(args[0],args[1]);
  6977. case "HARMEAN":
  6978. return this.HARMEAN(args[0],args[1]);
  6979. case "DATETODAY":
  6980. return this.DATETODAY(args[0]);
  6981. case "DAYTODATE":
  6982. return this.DAYTODATE(args[0]);
  6983. case "TIMETOSEC":
  6984. return this.TIMETOSEC(args[0]);
  6985. case "SECTOTIME":
  6986. return this.SECTOTIME(args[0]);
  6987. case 'MOD':
  6988. return this.MOD(args[0],args[1]);
  6989. case 'POW':
  6990. return this.POW(args[0],args[1]);
  6991. case 'CEILING':
  6992. return this.CEILING(args[0]);
  6993. case 'FLOOR':
  6994. return this.FLOOR(args[0]);
  6995. case "BETWEEN":
  6996. return this.BETWEEN(args[0], args[1],args[2]);
  6997. case "ANY":
  6998. return this.ANY(args[0],args[1]);
  6999. case "ALL":
  7000. return this.ALL(args[0],args[1]);
  7001. case "ALIGNRIGHT":
  7002. return this.ALIGNRIGHT(args[0]);
  7003. //三角函数
  7004. case 'ATAN':
  7005. return this.Trigonometric(args[0], Math.atan);
  7006. case 'ACOS':
  7007. return this.ACOS(args[0]);
  7008. case 'ASIN':
  7009. return this.ASIN(args[0]);
  7010. case 'COS':
  7011. return this.Trigonometric(args[0], Math.cos);
  7012. case 'SIN':
  7013. return this.Trigonometric(args[0], Math.sin);
  7014. case 'TAN':
  7015. return this.Trigonometric(args[0], Math.tan);
  7016. case 'LN':
  7017. return this.Trigonometric(args[0], Math.log);
  7018. case 'LOG':
  7019. return this.Trigonometric(args[0], Math.log10);
  7020. case 'EXP':
  7021. return this.Trigonometric(args[0], Math.exp);
  7022. case 'SQRT':
  7023. return this.Trigonometric(args[0], Math.sqrt);
  7024. default:
  7025. this.ThrowUnexpectedNode(node,'函数'+name+'不存在');
  7026. }
  7027. }
  7028. //调用自定义函数 返回数据格式{Out:输出数据, Draw:绘图数据(可选)}
  7029. this.CallCustomFunction=function(name, args, symbolData, node)
  7030. {
  7031. var functionInfo=g_JSComplierResource.CustomFunction.Data.get(name);
  7032. var dwonloadData=symbolData.GetStockCacheData({ CustomName:name, Node:node });
  7033. if (!functionInfo.Invoke)
  7034. return { Out: dwonloadData }
  7035. JSConsole.Complier.Log('[JSAlgorithm::CallCustomFunction] call custom function functionInfo=',functionInfo);
  7036. var self=this;
  7037. var obj=
  7038. {
  7039. Name:name,
  7040. Args:args,
  7041. Symbol:symbolData.Symbol, Period:symbolData.Period, Right:symbolData.Right,
  7042. KData:symbolData.Data, //K线数据
  7043. DownloadData:dwonloadData,
  7044. ThrowError:function(error)
  7045. {
  7046. self.ThrowUnexpectedNode(node, error);
  7047. }
  7048. };
  7049. return functionInfo.Invoke(obj);
  7050. }
  7051. this.ThrowUnexpectedNode=function(node,message)
  7052. {
  7053. let marker=node.Marker;
  7054. let msg=message || "执行异常";
  7055. return this.ErrorHandler.ThrowError(marker.Index,marker.Line,marker.Column,msg);
  7056. }
  7057. }
  7058. //是否有是有效的数字
  7059. JSAlgorithm.prototype.IsNumber=function(value)
  7060. {
  7061. if (value==null) return false;
  7062. if (isNaN(value)) return false;
  7063. return true;
  7064. }
  7065. //是否是整形
  7066. JSAlgorithm.prototype.IsInteger=function(x)
  7067. {
  7068. return (typeof x === 'number') && (x % 1 === 0);
  7069. }
  7070. //是否有是有效的除数
  7071. JSAlgorithm.prototype.IsDivideNumber=function(value)
  7072. {
  7073. if (value==null) return false;
  7074. if (isNaN(value)) return false;
  7075. if (value==0) return false;
  7076. return true;
  7077. }
  7078. //取模
  7079. JSAlgorithm.MOD=function(number,divisor)
  7080. {
  7081. if( (number < 0 && divisor < 0) || (number >=0 && divisor >= 0)) //同号
  7082. {
  7083. if(parseInt(number) == number && parseInt(divisor) == divisor) //全为整数
  7084. {
  7085. return number%divisor;
  7086. }
  7087. else //被除数-(整商×除数)之后在第一位小数位进行四舍五入
  7088. {
  7089. var value = parseFloat((number - (Math.floor(number/divisor) * divisor)).toFixed(1));
  7090. return value;
  7091. }
  7092. }
  7093. else //异号
  7094. {
  7095. var absNumber = Math.abs(number); //绝对值
  7096. var absDivisor = Math.abs(divisor); //绝对值
  7097. var value = Math.abs(Math.abs(divisor) * (Math.floor(absNumber/absDivisor) + 1) - Math.abs(number));
  7098. if(divisor < 0) value = -value
  7099. return value;
  7100. }
  7101. }
  7102. //是否是字符串
  7103. JSAlgorithm.prototype.IsString=function(value)
  7104. {
  7105. if (value && typeof(value)=='string') return true;
  7106. return false;
  7107. }
  7108. /*
  7109. 绘图函数
  7110. */
  7111. function JSDraw(errorHandler, symbolData)
  7112. {
  7113. this.ErrorHandler=errorHandler;
  7114. this.SymbolData = symbolData;
  7115. this.DRAWTEXT=function(condition,price,text)
  7116. {
  7117. let drawData=[];
  7118. let result={DrawData:drawData, DrawType:'DRAWTEXT',Text:text};
  7119. if (Array.isArray(condition))
  7120. {
  7121. var IsNumber=this.IsNumber(price);
  7122. var isFixedPosition=false;
  7123. if (price==="TOP"|| price==="BOTTOM")
  7124. {
  7125. result.FixedPosition=price;
  7126. isFixedPosition=true;
  7127. }
  7128. for(var i=0; i<condition.length; ++i)
  7129. {
  7130. drawData[i]=null;
  7131. if (isNaN(condition[i]) || !condition[i]) continue;
  7132. if (IsNumber || isFixedPosition)
  7133. {
  7134. drawData[i]=price;
  7135. }
  7136. else
  7137. {
  7138. if (this.IsNumber(price[i])) drawData[i]=price[i];
  7139. }
  7140. }
  7141. }
  7142. else if (this.IsNumber(condition) && condition)
  7143. {
  7144. var IsNumber=this.IsNumber(price);
  7145. var isFixedPosition=false;
  7146. if (price==="TOP"|| price==="BOTTOM")
  7147. {
  7148. result.FixedPosition=price;
  7149. isFixedPosition=true;
  7150. }
  7151. for(var i=0;i<this.SymbolData.Data.Data.length;++i)
  7152. {
  7153. if (IsNumber || isFixedPosition)
  7154. {
  7155. drawData[i]=price;
  7156. }
  7157. else
  7158. {
  7159. if (this.IsNumber(price[i])) drawData[i]=price[i];
  7160. }
  7161. }
  7162. }
  7163. return result;
  7164. }
  7165. this.DRAWTEXT_FIX=function(condition,x,y,type,text)
  7166. {
  7167. let result={Position:null, DrawType:'DRAWTEXT_FIX',Text:text};
  7168. if (condition.length<=0) return result;
  7169. for(var i in condition)
  7170. {
  7171. if (isNaN(condition[i]) || !condition[i]) continue;
  7172. result.Position={X:x, Y:y, Type:type};
  7173. return result;
  7174. }
  7175. return result;
  7176. }
  7177. //direction 文字Y轴位置 0=middle 1=价格的顶部 2=价格的底部
  7178. //offset 文字Y轴偏移
  7179. this.SUPERDRAWTEXT = function (condition, price, text, direction, offset)
  7180. {
  7181. let drawData = [];
  7182. let result = { DrawData: drawData, DrawType: 'SUPERDRAWTEXT', Text: text, YOffset: offset, Direction: direction, TextAlign: 'center' };
  7183. if (condition.length <= 0) return result;
  7184. var IsNumber = typeof (price) == "number";
  7185. for (var i in condition)
  7186. {
  7187. drawData[i] = null;
  7188. if (isNaN(condition[i]) || !condition[i]) continue;
  7189. if (IsNumber)
  7190. {
  7191. drawData[i] = price;
  7192. }
  7193. else
  7194. {
  7195. if (this.IsNumber(price[i])) drawData[i] = price[i];
  7196. }
  7197. }
  7198. return result;
  7199. }
  7200. this.STICKLINE=function(condition,data,data2,width,type)
  7201. {
  7202. let drawData=[];
  7203. let result={DrawData:drawData, DrawType:'STICKLINE',Width:width, Type:type};
  7204. var IsNumber=typeof(data)=="number";
  7205. var IsNumber2=typeof(data2)=="number";
  7206. if (Array.isArray(condition)) //数组
  7207. {
  7208. if(condition.length<=0) return result;
  7209. for(var i in condition)
  7210. {
  7211. drawData[i]=null;
  7212. if (isNaN(condition[i]) || !condition[i]) continue;
  7213. if (IsNumber && IsNumber2)
  7214. {
  7215. drawData[i]={Value:data,Value2:data2};
  7216. }
  7217. else if (IsNumber && !IsNumber2)
  7218. {
  7219. if (isNaN(data2[i])) continue;
  7220. drawData[i]={Value:data,Value2:data2[i]};
  7221. }
  7222. else if (!IsNumber && IsNumber2)
  7223. {
  7224. if (isNaN(data[i])) continue;
  7225. drawData[i]={Value:data[i],Value2:data2};
  7226. }
  7227. else
  7228. {
  7229. if (isNaN(data[i]) || isNaN(data2[i])) continue;
  7230. drawData[i]={Value:data[i],Value2:data2[i]};
  7231. }
  7232. }
  7233. }
  7234. else
  7235. {
  7236. if(!condition) return result;
  7237. for(var i=0;i<this.SymbolData.Data.Data.length;++i) //以K线长度为数据长度
  7238. {
  7239. drawData[i]=null;
  7240. if (IsNumber && IsNumber2)
  7241. {
  7242. drawData[i]={Value:data,Value2:data2};
  7243. }
  7244. else if (IsNumber && !IsNumber2)
  7245. {
  7246. if (!this.IsNumber(data2[i])) continue;
  7247. drawData[i]={Value:data,Value2:data2[i]};
  7248. }
  7249. else if (!IsNumber && IsNumber2)
  7250. {
  7251. if (!this.IsNumber(data[i])) continue;
  7252. drawData[i]={Value:data[i],Value2:data2};
  7253. }
  7254. else
  7255. {
  7256. if (!this.IsNumber(data[i]) || !this.IsNumber(data2[i])) continue;
  7257. drawData[i]={Value:data[i],Value2:data2[i]};
  7258. }
  7259. }
  7260. }
  7261. return result;
  7262. }
  7263. /*
  7264. DRAWLINE 绘制直线段
  7265. 在图形上绘制直线段
  7266. 用法 DRAWLINE(COND1PRICE1COND2PRICE2EXPAND)
  7267. 当COND1条件满足时在PRICE1位置画直线起点当COND2条件满足时在PRICE2位置画直线终点EXPAND为延长类型
  7268. 例如 DRAWLINE(HIGH>=HHV(HIGH,20),HIGH,LOW<=LLV(LOW,20),LOW,1) 表示在创20天新高与创20天新低之间画直线并且向右延长
  7269. */
  7270. this.DRAWLINE=function(condition,data,condition2,data2,expand)
  7271. {
  7272. let drawData=[];
  7273. let result={DrawData:drawData, DrawType:'DRAWLINE', Expand:expand};
  7274. if(condition.length<=0) return result;
  7275. let count=Math.max(condition.length,condition2.length);
  7276. let bFirstPoint=false;
  7277. let bSecondPont=false;
  7278. let lineCache={Start:{ },End:{ }, List:new Array()};
  7279. for(let i=0;i<count;++i)
  7280. {
  7281. drawData[i]=null;
  7282. if (i<condition.length && i<condition2.length)
  7283. {
  7284. if (bFirstPoint==false && bSecondPont==false)
  7285. {
  7286. if (condition[i]==null || !condition[i]) continue;
  7287. bFirstPoint=true;
  7288. lineCache.Start={ID:i, Value:data[i]}; //第1个点
  7289. }
  7290. else if (bFirstPoint==true && bSecondPont==false)
  7291. {
  7292. var bCondition2=(condition2[i]!=null && condition2[i]); //条件2
  7293. if (!bCondition2) continue;
  7294. if (bCondition2)
  7295. {
  7296. bSecondPont=true;
  7297. lineCache.End={ID:i, Value:data2[i]}; //第2个点
  7298. }
  7299. }
  7300. if (bFirstPoint==true && bSecondPont==true) //2个点都有了, 等待下一次的点出现
  7301. {
  7302. let lineData=this.CalculateDrawLine(lineCache); //计算2个点的线上 其他点的数值
  7303. for(let j in lineData)
  7304. {
  7305. let item=lineData[j];
  7306. drawData[item.ID]=item.Value;
  7307. }
  7308. bFirstPoint=bSecondPont=false;
  7309. lineCache={Start:{ },End:{ }};
  7310. }
  7311. }
  7312. }
  7313. if (expand==1) //右延长线
  7314. {
  7315. var x2=null;
  7316. for(var i=drawData.length-1;i>=0;--i)
  7317. {
  7318. if (this.IsNumber(drawData[i]))
  7319. {
  7320. x2=i;
  7321. break;
  7322. }
  7323. }
  7324. //y3=(y1-y2)*(x3-x1)/(x2-x1)
  7325. if (x2!=null && x2-1>=0)
  7326. {
  7327. var x1=x2-1;
  7328. for(var i=x2+1;i<drawData.length;++i)
  7329. {
  7330. var y1=drawData[x1];
  7331. var y2=drawData[x2];
  7332. var y3=(y1-y2)*(i-x1)/(x2-x1);
  7333. drawData[i]=y1-y3;
  7334. }
  7335. }
  7336. }
  7337. return result;
  7338. }
  7339. /*
  7340. 画出带状线.
  7341. 用法: DRAWBAND(VAL1,COLOR1,VAL2,COLOR2),当VAL1>VAL2时,在VAL1和VAL2之间填充COLOR1;当VAL1<VAL2时,填充COLOR2,这里的颜色均使用RGB函数计算得到.
  7342. 例如: DRAWBAND(OPEN,RGB(0,224,224),CLOSE,RGB(255,96,96));
  7343. */
  7344. this.DRAWBAND=function(data,color,data2,color2)
  7345. {
  7346. let drawData=[];
  7347. let result = { DrawData: drawData, DrawType: 'DRAWBAND', Color: [color.toLowerCase(), color2.toLowerCase()]};
  7348. let count=Math.max(data.length, data2.length);
  7349. for(let i=0;i<count;++i)
  7350. {
  7351. let item={Value:null, Value2:null};
  7352. if (i<data.length) item.Value=data[i];
  7353. if (i<data2.length) item.Value2=data2[i];
  7354. drawData.push(item);
  7355. }
  7356. return result;
  7357. }
  7358. this.DRAWKLINE = function (high, open, low, close)
  7359. {
  7360. let drawData = [];
  7361. let result = { DrawData: drawData, DrawType: 'DRAWKLINE' };
  7362. let count = Math.max(high.length, open.length, low.length, close.length);
  7363. for (let i = 0; i < count; ++i)
  7364. {
  7365. let item = { Open: null, High: null, Low: null, Close: null };
  7366. if (i < high.length && i < open.length && i < low.length && i < close.length)
  7367. {
  7368. item.Open = open[i];
  7369. item.High = high[i];
  7370. item.Low = low[i];
  7371. item.Close = close[i];
  7372. }
  7373. drawData[i] = item;
  7374. }
  7375. return result;
  7376. }
  7377. //满足条件画一根K线
  7378. this.DRAWKLINE_IF = function (condition, high, open, low, close)
  7379. {
  7380. let drawData = [];
  7381. let result = { DrawData: drawData, DrawType: 'DRAWKLINE_IF' };
  7382. let count = Math.max(condition.length, high.length, open.length, low.length, close.length);
  7383. for (let i = 0; i < count; ++i) {
  7384. let item = { Open: null, High: null, Low: null, Close: null };
  7385. if (i < high.length && i < open.length && i < low.length && i < close.length && i < condition.length)
  7386. {
  7387. if (condition[i])
  7388. {
  7389. item.Open = open[i];
  7390. item.High = high[i];
  7391. item.Low = low[i];
  7392. item.Close = close[i];
  7393. }
  7394. }
  7395. drawData[i] = item;
  7396. }
  7397. return result;
  7398. }
  7399. /*
  7400. DRAWCOLORKLINE 绘制K线
  7401. 用法
  7402. DRAWCOLORKLINE(Cond,Color,Empty);
  7403. 满足Cond条件时按照Color颜色绘制K线根据Empty标志判断是空心还是实心COLOR代表颜色Empty非0为空心
  7404. 不支持将该函数定义为变量即不支持下面的写法
  7405. A:DRAWCOLORKLINE(Cond,Color,Empty);
  7406. DRAWCOLORKLINE(C>O,COLORBLUE,0);//收盘价大于开盘价,用蓝色绘制实心K线
  7407. */
  7408. this.DRAWCOLORKLINE=function(condition, color, empty)
  7409. {
  7410. let drawData=[];
  7411. let result={ DrawData:drawData, DrawType:'DRAWCOLORKLINE', IsEmptyBar:!(empty==0), Color:color };
  7412. if (Array.isArray(condition)) //数组
  7413. {
  7414. for(var i=0; i<condition.length && i<this.SymbolData.Data.Data.length; ++i)
  7415. {
  7416. drawData[i]=null;
  7417. var condItem=condition[i];
  7418. if (!condItem) continue;
  7419. var kItem=this.SymbolData.Data.Data[i];
  7420. if (!kItem) continue;
  7421. drawData[i]={Open:kItem.Open,High:kItem.High, Low:kItem.Low, Close:kItem.Close};
  7422. }
  7423. }
  7424. else
  7425. {
  7426. if (condition)
  7427. {
  7428. for(var i=0;i<this.SymbolData.Data.Data.length;++i) //以K线长度为数据长度
  7429. {
  7430. drawData[i]=null;
  7431. var kItem=this.SymbolData.Data.Data[i];
  7432. if (!kItem) continue;
  7433. drawData[i]={Open:kItem.Open,High:kItem.High, Low:kItem.Low, Close:kItem.Close };
  7434. }
  7435. }
  7436. }
  7437. return result;
  7438. }
  7439. /*
  7440. PLOYLINE 折线段
  7441. 在图形上绘制折线段
  7442. 用法 PLOYLINE(CONDPRICE)当COND条件满足时以PRICE位置为顶点画折线连接
  7443. 例如 PLOYLINE(HIGH>=HHV(HIGH,20),HIGH)表示在创20天新高点之间画折线
  7444. */
  7445. this.POLYLINE = function (condition, data)
  7446. {
  7447. let drawData = [];
  7448. let result = { DrawData: drawData, DrawType: 'POLYLINE' };
  7449. let isNumber = typeof (data) == 'number';
  7450. let bFirstPoint = false;
  7451. let bSecondPont = false;
  7452. if (isNumber)
  7453. {
  7454. for (let i in condition)
  7455. {
  7456. drawData[i] = null;
  7457. if (bFirstPoint == false)
  7458. {
  7459. if (!condition[i]) continue;
  7460. drawData[i] = data;
  7461. bFirstPoint = true;
  7462. }
  7463. else {
  7464. drawData[i] = data;
  7465. }
  7466. }
  7467. }
  7468. else
  7469. {
  7470. let lineCache = { Start: {}, End: {}, List: new Array() };
  7471. for (let i in condition)
  7472. {
  7473. drawData[i] = null;
  7474. if (bFirstPoint == false && bSecondPont == false)
  7475. {
  7476. if (condition[i] == null || !condition[i]) continue;
  7477. if (i >= data.length || !this.IsNumber(data[i])) continue;
  7478. bFirstPoint = true;
  7479. lineCache.Start = { ID: parseInt(i), Value: data[i] }; //第1个点
  7480. }
  7481. else if (bFirstPoint == true && bSecondPont == false)
  7482. {
  7483. if (condition[i] == null || !condition[i]) continue;
  7484. if (i >= data.length || !this.IsNumber(data[i])) continue;
  7485. lineCache.End = { ID: parseInt(i), Value: data[i] }; //第2个点
  7486. //根据起始点和结束点 计算中间各个点的数据
  7487. let lineData = this.CalculateDrawLine(lineCache); //计算2个点的线上 其他点的数值
  7488. for (let j in lineData)
  7489. {
  7490. let item = lineData[j];
  7491. drawData[item.ID] = item.Value;
  7492. }
  7493. let start = { ID: lineCache.End.ID, Value: lineCache.End.Value };
  7494. lineCache = { Start: start, End: {} };
  7495. }
  7496. }
  7497. }
  7498. return result
  7499. }
  7500. /*
  7501. 画出数字.
  7502. 用法:
  7503. DRAWNUMBER(COND,PRICE,NUMBER),当COND条件满足时,在PRICE位置书写数字NUMBER.
  7504. 例如:
  7505. DRAWNUMBER(CLOSE/OPEN>1.08,LOW,C)表示当日实体阳线大于8%时在最低价位置显示收盘价.
  7506. */
  7507. this.DRAWNUMBER = function (condition, data, data2,decimal)
  7508. {
  7509. let drawData={ Value:[], Text:[] };
  7510. let result={ DrawData:drawData, DrawType:'DRAWNUMBER' };
  7511. var dec=2; //小数位数
  7512. if (IFrameSplitOperator.IsNumber(decimal)) dec=decimal;
  7513. var priceData={ DataType:0, SingleValue:null, ArrayValue:null }; //SingleValue=单值 ArrayValue=数组
  7514. if (Array.isArray(data))
  7515. {
  7516. priceData.ArrayValue=data;
  7517. priceData.DataType=2;
  7518. }
  7519. else
  7520. {
  7521. if (data==="TOP"|| data==="BOTTOM") result.FixedPosition=data;
  7522. priceData.SingleValue=data;
  7523. priceData.DataType=1;
  7524. }
  7525. var numberData={ DataType:0, SingleValue:null,ArrayValue:null };
  7526. if (Array.isArray(data2))
  7527. {
  7528. numberData.ArrayValue=data2;
  7529. numberData.DataType=2;
  7530. }
  7531. else
  7532. { //单值
  7533. numberData.SingleValue=data2;
  7534. numberData.DataType=1;
  7535. if (IFrameSplitOperator.IsNumber(data2))
  7536. {
  7537. if (IFrameSplitOperator.IsInteger(data2)) numberData.SingleValue=data2.toString();
  7538. else text=data2.toFixed(dec);
  7539. }
  7540. }
  7541. if (Array.isArray(condition))
  7542. {
  7543. for(var i=0; i<condition.length; ++i)
  7544. {
  7545. drawData.Value[i]=null;
  7546. if (!condition[i]) continue;
  7547. drawData.Value[i]=this.DRAWNUMBER_Temp_PriceItem(i,priceData);
  7548. drawData.Text[i]=this.DRAWNUMBER_Temp_NumberItem(i,numberData,dec);
  7549. }
  7550. }
  7551. else if (this.IsNumber(condition) && condition)
  7552. {
  7553. for(var i=0;i<this.SymbolData.Data.Data.length;++i)
  7554. {
  7555. drawData.Value[i]=this.DRAWNUMBER_Temp_PriceItem(i,priceData);
  7556. drawData.Text[i]=this.DRAWNUMBER_Temp_NumberItem(i,numberData,dec);
  7557. }
  7558. }
  7559. return result;
  7560. }
  7561. this.DRAWNUMBER_Temp_PriceItem=function(index, priceData)
  7562. {
  7563. if (!priceData) return null;
  7564. if (priceData.DataType==1) return priceData.SingleValue;
  7565. if (!IFrameSplitOperator.IsNonEmptyArray(priceData.ArrayValue)) return null;
  7566. return priceData.ArrayValue[index];
  7567. }
  7568. this.DRAWNUMBER_Temp_NumberItem=function(index,numberData,decimal)
  7569. {
  7570. if (!numberData) return null;
  7571. if (numberData.DataType==1) return numberData.SingleValue;
  7572. if (!IFrameSplitOperator.IsNonEmptyArray(numberData.ArrayValue)) return null;
  7573. var value=numberData.ArrayValue[index];
  7574. if (this.IsNumber(value))
  7575. {
  7576. if (IFrameSplitOperator.IsInteger(value)) return value.toString();
  7577. else return value.toFixed(decimal);
  7578. }
  7579. return value.toString();
  7580. }
  7581. /*
  7582. 在图形上绘制小图标.
  7583. 用法:
  7584. DRAWICON(COND,PRICE,TYPE),当COND条件满足时,在PRICE位置画TYPE号图标(TYPE为1--41).
  7585. 例如:
  7586. DRAWICON(CLOSE>OPEN,LOW,1)表示当收阳时在最低价位置画1号图标.
  7587. */
  7588. this.DRAWICON = function (condition, data, type, markID)
  7589. {
  7590. if (IFrameSplitOperator.IsString(type)) //把ICO1=>1
  7591. {
  7592. var value=type.replace('ICO',"");
  7593. type=parseInt(value);
  7594. }
  7595. let icon = g_JSComplierResource.GetDrawTextIcon(type);
  7596. if (!icon) icon = { Symbol: '●', Color: 'rgb(0,139,69)'};
  7597. let drawData = [];
  7598. let result = { DrawData: drawData, DrawType: 'DRAWICON', Icon: icon , IconID:type};
  7599. if (markID) result.MarkID=markID;
  7600. if (condition.length <= 0) return result;
  7601. var IsNumber = typeof (data) == "number";
  7602. if (typeof (condition) == 'number')
  7603. {
  7604. if (!condition) return result;
  7605. for (var i = 0; i < this.SymbolData.Data.Data.length; ++i)
  7606. {
  7607. if (IsNumber)
  7608. {
  7609. drawData[i] = data;
  7610. }
  7611. else
  7612. {
  7613. if (i < data.length && this.IsNumber(data[i])) drawData[i] = data[i];
  7614. else drawData[i] = null;
  7615. }
  7616. }
  7617. return result;
  7618. }
  7619. for (var i in condition)
  7620. {
  7621. drawData[i] = null;
  7622. if (!condition[i]) continue;
  7623. if (IsNumber)
  7624. {
  7625. drawData[i] = data;
  7626. }
  7627. else
  7628. {
  7629. if (this.IsNumber(data[i])) drawData[i] = data[i];
  7630. }
  7631. }
  7632. return result;
  7633. }
  7634. /*
  7635. ICON在k线图上显示小图标
  7636. 用法ICON(TYPE,ICON);
  7637. 当TYPE为1则在K线最高价位置显示图标ICON当TYPE为0则在最低价位置显示
  7638. 图标ICON
  7639. 1该函数与判断条件连用COND,ICON(TYPE,ICON);
  7640. 2该函数支持在函数后设置垂直对齐方式VALIGN0上对齐VALIGN1中对齐VALIGN2下对齐
  7641. 即可以写为如下格式
  7642. CLOSE<OPEN,ICON(1,'阴'),VALIGN0;
  7643. 例1
  7644. CLOSE>OPEN,ICON(1,'ICO1');//表示K线收盘大于开盘时,在最高价上显示图标1。
  7645. 写完ICON(1, 以后点击插入图标按钮再单击选中的图标插入到函数中图标用
  7646. 'ICO1'~'ICO105'表示
  7647. */
  7648. this.ICON=function(position, type)
  7649. {
  7650. if (IFrameSplitOperator.IsString(type)) //把ICO1=>1
  7651. {
  7652. var value=type.replace('ICO',"");
  7653. type=parseInt(value);
  7654. }
  7655. var icon=g_JSComplierResource.GetDrawTextIcon(type);
  7656. if (!icon) icon={ Symbol: '●', Color: 'rgb(0,139,69)'};
  7657. let drawData=[];
  7658. let result={DrawData:drawData, DrawType:'ICON',Icon:icon};
  7659. for(var i=0;i<this.SymbolData.Data.Data.length;++i)
  7660. {
  7661. var kItem=this.SymbolData.Data.Data[i];
  7662. if (!kItem) continue;
  7663. if (position==0) drawData[i]=kItem.Low;
  7664. else if (position==1) drawData[i]=kItem.High;
  7665. }
  7666. return result;
  7667. }
  7668. // 相对位置上画矩形.
  7669. //用法: DRAWRECTREL(LEFT,TOP,RIGHT,BOTTOM,COLOR),以图形窗口(LEFT,TOP)为左上角,(RIGHT,BOTTOM)为右下角绘制矩形,坐标单位是窗口沿水平和垂直方向的1/1000,取值范围是0—999,超出范围则可能显示在图形窗口外,矩形中间填充颜色COLOR,COLOR为0表示不填充.
  7670. //例如: DRAWRECTREL(0,0,500,500,RGB(255,255,0))表示在图形最左上部1/4位置用黄色绘制矩形
  7671. this.DRAWRECTREL = function (left, top, right, bottom, color)
  7672. {
  7673. let drawData =
  7674. {
  7675. Rect:
  7676. {
  7677. Left: Math.min(left,right), Top: Math.min(top,bottom),
  7678. Right: Math.max(left,right), Bottom: Math.max(top,bottom)
  7679. },
  7680. Color: color
  7681. };
  7682. if (color == 0) drawData.Color = null;
  7683. let result = { DrawData: drawData, DrawType: 'DRAWRECTREL' };
  7684. return result;
  7685. }
  7686. //DRAWTEXTREL(X,Y,TEXT),在图形窗口(X,Y)坐标位置书写文字TEXT,坐标单位是窗口沿水平和垂直方向的1/1000,X、Y取值范围是0—999,超出范围则可能显示在图形窗口外。
  7687. //例如:DRAWTEXTREL(500,500,'注意')表示在图形中间位置显示'注意'字样。
  7688. this.DRAWTEXTREL=function(x, y, text)
  7689. {
  7690. let drawData={ Point:{X:x, Y:y} };
  7691. if (IFrameSplitOperator.IsString(text))
  7692. drawData.Text=text;
  7693. else if (IFrameSplitOperator.IsNonEmptyArray(text))
  7694. drawData.Text=text[0];
  7695. let result={DrawData:drawData, DrawType:'DRAWTEXTREL'};
  7696. return result;
  7697. }
  7698. //DRAWTEXTABS(X,Y,TEXT),在图形窗口(X,Y)坐标位置书写文字TEXT,坐标单位是像素,图形窗口左上角坐标为(0,0)。
  7699. //例如:DRAWTEXTABS(0,0,'注意')表示在图形最左上角位置显示'注意'字样。
  7700. this.DRAWTEXTABS=function(x, y, text)
  7701. {
  7702. let drawData={ Point:{X:x, Y:y} };
  7703. if (IFrameSplitOperator.IsString(text))
  7704. drawData.Text=text;
  7705. else if (IFrameSplitOperator.IsNonEmptyArray(text))
  7706. drawData.Text=text[0];
  7707. let result={DrawData:drawData, DrawType:'DRAWTEXTABS'};
  7708. return result;
  7709. }
  7710. //填充背景.
  7711. //用法: DRAWGBK(COND,COLOR1,COLOR2,colorAngle) colorAngle=渐近色角度
  7712. //例如: DRAWGBK(O>C,RGB(0,255,0),RGB(255,0,0),0);
  7713. this.DRAWGBK=function(condition, color, color2, colorAngle)
  7714. {
  7715. let drawData={ Color:[], Angle:colorAngle };
  7716. if (color) drawData.Color.push(color);
  7717. if (color2) drawData.Color.push(color2);
  7718. let result={DrawData:null, DrawType:'DRAWGBK'};
  7719. if (Array.isArray(condition))
  7720. {
  7721. for(var i in condition)
  7722. {
  7723. var item=condition[i];
  7724. if (item)
  7725. {
  7726. result.DrawData=drawData;
  7727. break;
  7728. }
  7729. }
  7730. }
  7731. else
  7732. {
  7733. if (condition) result.DrawData=drawData;
  7734. }
  7735. return result;
  7736. }
  7737. this.DRAWGBK2=function(condition, color, color2, colorAngle)
  7738. {
  7739. let drawData={ Color:[], Angle:colorAngle };
  7740. if (color) drawData.Color.push(color);
  7741. if (color2) drawData.Color.push(color2);
  7742. let result={DrawData:null, DrawType:'DRAWGBK2'};
  7743. if (Array.isArray(condition))
  7744. {
  7745. drawData.Data=[];
  7746. for(var i in condition)
  7747. {
  7748. var item=condition[i];
  7749. drawData.Data[i]=item ? 1:0;
  7750. }
  7751. result.DrawData=drawData;
  7752. }
  7753. else
  7754. {
  7755. if (condition)
  7756. {
  7757. result.DrawData=drawData;
  7758. result.DrawType="DRAWGBK";
  7759. }
  7760. }
  7761. return result;
  7762. }
  7763. //填充部分背景.
  7764. //用法:
  7765. //DRAWGBK_DIV(COND,COLOR1,COLOR2,填色方式,填充范围),填充满足COND条件的背景区域
  7766. //填色方式:0是上下渐进 1是左右渐进 2是用COLOR1画框线 3是用COLOR1画框线, 用COLOR2填充
  7767. //填充范围:0为整个区域 1为最高最低区 2为开盘收盘区
  7768. //例如:
  7769. //DRAWGBK_DIV(C>O,RGB(0,255,0),RGB(255,0,0),0,0);
  7770. this.DRAWGBK_DIV=function(condition, color, color2, colorType, fillType)
  7771. {
  7772. var drawData={ AryColor:[color, color2], ColorType:colorType, FillType:fillType, Data:[] };
  7773. var result={ DrawData:drawData, DrawType:'DRAWGBK_DIV' };
  7774. if (!this.SymbolData || !this.SymbolData.Data || !IFrameSplitOperator.IsNonEmptyArray(this.SymbolData.Data.Data)) return result;
  7775. var aryKData=this.SymbolData.Data.Data;
  7776. if (Array.isArray(condition))
  7777. {
  7778. for(var i=0; i<aryKData.length; ++i)
  7779. {
  7780. var condItem=condition[i];
  7781. var item=null;
  7782. if (condItem)
  7783. {
  7784. var kItem=aryKData[i];
  7785. if (fillType==1) item={ AryValue:[kItem.High, kItem.Low] }
  7786. else if (fillType==2) item={ AryValue:[kItem.Open, kItem.Close] }
  7787. else item={ AryValue:null };
  7788. }
  7789. drawData.Data[i]=item;
  7790. }
  7791. }
  7792. else
  7793. {
  7794. if (condition)
  7795. {
  7796. for(var i=0; i<aryKData.length; ++i)
  7797. {
  7798. var kItem=aryKData[i];
  7799. var item=null;
  7800. if (fillType==1) item={ AryValue:[kItem.High, kItem.Low] }
  7801. else if (fillType==2) item={ AryValue:[kItem.Open, kItem.Close] }
  7802. else item={ AryValue:null };
  7803. drawData.Data[i]=item;
  7804. }
  7805. }
  7806. }
  7807. return result;
  7808. }
  7809. this.RGB = function (r, g, b)
  7810. {
  7811. var rgb = `rgb(${r},${g},${b})`;
  7812. return rgb;
  7813. }
  7814. this.RGBA = function (r, g, b, a)
  7815. {
  7816. var rgba = `rgba(${r},${g},${b},${a})`;
  7817. return rgba;
  7818. }
  7819. this.UPCOLOR=function(color)
  7820. {
  7821. return color;
  7822. }
  7823. this.DOWNCOLOR=function(color)
  7824. {
  7825. return color;
  7826. }
  7827. this.STICKTYPE=function(value)
  7828. {
  7829. return value;
  7830. }
  7831. //数据左右偏移
  7832. this.XMOVE=function(offset)
  7833. {
  7834. return offset;
  7835. }
  7836. //数据上下偏移
  7837. this.YMOVE=function(offset)
  7838. {
  7839. return offset;
  7840. }
  7841. this.LINEDASH=function(aryData)
  7842. {
  7843. if (IFrameSplitOperator.IsNonEmptyArray(aryData)) return aryData.slice();
  7844. return [];
  7845. }
  7846. //该函数和DRAWTEXT连用
  7847. //{ Color:背景色, Border:边框颜色, Margin=[上,下,左, 右] }
  7848. this.BACKGROUND=function(color, borderColor, left, right, top, bottom)
  7849. {
  7850. var bg={ Margin:[0,1,1,1] };
  7851. if (color) bg.Color=color;
  7852. if (borderColor) bg.Border=borderColor;
  7853. if (IFrameSplitOperator.IsNumber(left)) bg.Margin[2]=left;
  7854. if (IFrameSplitOperator.IsNumber(right)) bg.Margin[3]=right;
  7855. if (IFrameSplitOperator.IsNumber(top)) bg.Margin[0]=top;
  7856. if (IFrameSplitOperator.IsNumber(bottom)) bg.Margin[1]=bottom;
  7857. return bg;
  7858. }
  7859. //该函数和DRAWTEXT, DRAWNUMBER连用
  7860. //{ color:线段颜色, lineWidth:宽度 lineType:线段样式0=直线 1=虚线}
  7861. this.CKLINE=function(color, lineWidth, lineType, lineDotted)
  7862. {
  7863. var drawData={ Color:color, LineWidth: 1, LineType:0, LineDot:[3,3] };
  7864. if (IFrameSplitOperator.IsPlusNumber(lineWidth)) drawData.LineWidth=lineWidth;
  7865. if (IFrameSplitOperator.IsPlusNumber(lineType)) drawData.LineType=lineType;
  7866. if (lineDotted)
  7867. {
  7868. let ary=lineDotted.split(',');
  7869. var dotted=[];
  7870. for(var i in ary)
  7871. {
  7872. var item=ary[i];
  7873. if (!item) continue;
  7874. var value=parseInt(ary[i]);
  7875. if (value<=0) continue;
  7876. dotted.push(value);
  7877. }
  7878. if (dotted.length>0) drawData.LineDotted=dotted;
  7879. }
  7880. drawData.Data=[];
  7881. for(var i=0;i<this.SymbolData.Data.Data.length;++i)
  7882. {
  7883. var item=this.SymbolData.Data.Data[i];
  7884. drawData.Data[i]={ High:item.High, Low:item.Low };
  7885. }
  7886. return drawData;
  7887. }
  7888. }
  7889. JSDraw.prototype.CalculateDrawLine=function(lineCache)
  7890. {
  7891. lineCache.List=[];
  7892. for(let i=lineCache.Start.ID; i<=lineCache.End.ID; ++i) lineCache.List.push(i);
  7893. let height=Math.abs(lineCache.Start.Value-lineCache.End.Value);
  7894. let width=lineCache.List.length-1;
  7895. var result=[];
  7896. result.push({ID:lineCache.Start.ID, Value:lineCache.Start.Value}); //第1个点
  7897. if (lineCache.Start.Value>lineCache.End.Value)
  7898. {
  7899. for(let i=1;i<lineCache.List.length-1;++i)
  7900. {
  7901. var value=height*(lineCache.List.length-1-i)/width+lineCache.End.Value;
  7902. result.push({ID:lineCache.List[i], Value:value});
  7903. }
  7904. }
  7905. else
  7906. {
  7907. for(let i=1;i<lineCache.List.length-1;++i)
  7908. {
  7909. var value=height*i/width+lineCache.Start.Value;
  7910. result.push({ID:lineCache.List[i], Value:value});
  7911. }
  7912. }
  7913. result.push({ID:lineCache.End.ID, Value:lineCache.End.Value}); //最后一个点
  7914. return result;
  7915. }
  7916. //是否有是有效的数字
  7917. JSDraw.prototype.IsNumber = function (value)
  7918. {
  7919. if (value == null) return false;
  7920. if (isNaN(value)) return false;
  7921. return true;
  7922. }
  7923. //是否是整形
  7924. JSDraw.prototype.IsInteger=function(x)
  7925. {
  7926. return (typeof x === 'number') && (x % 1 === 0);
  7927. }
  7928. JSDraw.prototype.IsDrawFunction=function(name)
  7929. {
  7930. let setFunctionName = new Set(
  7931. [
  7932. "STICKLINE", "DRAWTEXT", 'SUPERDRAWTEXT', "DRAWTEXT_FIX", 'DRAWLINE', 'DRAWBAND', "DRAWKLINE1","DRAWCOLORKLINE",
  7933. 'DRAWKLINE', 'DRAWKLINE_IF', 'PLOYLINE', 'POLYLINE', 'DRAWNUMBER', 'DRAWICON',"ICON",
  7934. 'DRAWRECTREL', "DRAWTEXTABS","DRAWTEXTREL", "DRAWGBK", "DRAWGBK2","DRAWGBK_DIV"
  7935. ]);
  7936. if (setFunctionName.has(name)) return true;
  7937. return false;
  7938. }
  7939. //http://www.newone.com.cn/helpcontroller/index?code=zszy_pc
  7940. var DYNAINFO_ARGUMENT_ID=
  7941. {
  7942. YCLOSE:3,
  7943. OPEN:4,
  7944. HIGH:5,
  7945. LOW:6,
  7946. CLOSE: 7,
  7947. VOL: 8,
  7948. AMOUNT: 10,
  7949. AMPLITUDE:13, //振幅
  7950. INCREASE:14, //涨幅
  7951. EXCHANGERATE:37, //换手率
  7952. };
  7953. function JSSymbolData(ast,option,jsExecute)
  7954. {
  7955. this.AST=ast; //语法树
  7956. this.Execute=jsExecute;
  7957. this.Symbol='600000.sh';
  7958. this.Name;
  7959. this.Data=null; //个股数据
  7960. this.SourceData = null; //不复权的个股数据
  7961. this.MarketValue = null; //总市值
  7962. this.Period=0; //周期
  7963. this.Right=0; //复权
  7964. this.DataType = 0; //默认K线数据 2=分钟走势图数据
  7965. this.KLineApiUrl = g_JSComplierResource.Domain+"/API/KLine2"; //日线
  7966. this.MinuteKLineApiUrl = g_JSComplierResource.Domain +'/API/KLine3'; //分钟K线
  7967. this.RealtimeApiUrl = g_JSComplierResource.Domain +'/API/stock'; //实时行情
  7968. this.StockHistoryDayApiUrl = g_JSComplierResource.Domain +'/API/StockHistoryDay'; //历史财务数据
  7969. this.StockHistoryDay3ApiUrl = g_JSComplierResource.Domain +'/API/StockHistoryDay3'; //历史财务数据
  7970. this.StockNewsAnalysisApiUrl = g_JSComplierResource.CacheDomain+'/cache/newsanalyze'; //新闻分析数据
  7971. this.MaxRequestDataCount=1000;
  7972. this.MaxRequestMinuteDayCount=5;
  7973. this.KLineDateTimeRange; //请求的K线日期范围
  7974. this.LatestData=new Map(); //最新行情
  7975. this.IndexData; //大盘指数
  7976. this.MarginData = new Map(); //融资融券
  7977. this.NewsAnalysisData = new Map(); //新闻统计
  7978. this.ExtendData = new Map(); //其他的扩展数据
  7979. this.ScriptIndexOutData=new Map(); //调用脚本执行返回的数据
  7980. this.OtherSymbolData=new Map(); //其他股票信息 key=symbol value=[historydata]
  7981. //股票数据缓存 key=函数名(参数) { Data: value=拟合的数据 , Error: }
  7982. //FinValue(id)
  7983. this.StockData=new Map();
  7984. this.NetworkFilter; //网络请求回调 function(data, callback);
  7985. this.DrawInfo; //当前屏信息
  7986. //使用option初始化
  7987. if (option)
  7988. {
  7989. if (option.HQDataType) this.DataType = option.HQDataType;
  7990. if (option.Data)
  7991. {
  7992. this.Data=option.Data;
  7993. if (this.DataType != 2) //2=分钟走势图数据 没有周期和复权
  7994. {
  7995. this.Period=option.Data.Period; //周期
  7996. this.Right=option.Data.Right; //复权
  7997. }
  7998. //this.Data=null;
  7999. }
  8000. if (option.SourceData) this.SourceData = option.SourceData;
  8001. if (option.Symbol) this.Symbol=option.Symbol;
  8002. if (option.Symbol) this.Symbol = option.Symbol;
  8003. if (option.MaxRequestDataCount>0) this.MaxRequestDataCount=option.MaxRequestDataCount;
  8004. if (option.MaxRequestMinuteDayCount>0) this.MaxRequestMinuteDayCount=option.MaxRequestMinuteDayCount;
  8005. if (option.KLineApiUrl) this.KLineApiUrl=option.KLineApiUrl;
  8006. if (option.NetworkFilter) this.NetworkFilter = option.NetworkFilter;
  8007. if (option.DayCount>0) this.DayCount=option.DayCount;
  8008. if (option.IsApiPeriod) this.IsApiPeriod=option.IsApiPeriod;
  8009. if (option.Right) this.Right=option.Right;
  8010. if (option.Period) this.Period=option.Period;
  8011. if (option.KLineRange) this.KLineDateTimeRange=option.KLineRange;
  8012. if (option.DrawInfo) this.DrawInfo=option.DrawInfo;
  8013. }
  8014. this.GetLatestDataKey=function(key)
  8015. {
  8016. var key=`DYNAINFO-${key}`;
  8017. return key;
  8018. }
  8019. //最新行情
  8020. this.GetLatestData=function(jobItem)
  8021. {
  8022. var aryArgs=this.JobArgumentsToArray(jobItem, 1);
  8023. var lID=aryArgs[0];
  8024. var key=this.GetLatestDataKey(lID);
  8025. if (this.LatestData.has(key)) return this.Execute.RunNextJob();
  8026. var self=this;
  8027. JSNetwork.HttpRequest({
  8028. url: self.RealtimeApiUrl,
  8029. data:
  8030. {
  8031. "field": ["name","symbol","yclose","open","price","high","low","vol","amount","date","time","increase","exchangerate","amplitude"],
  8032. "symbol": [this.Symbol]
  8033. },
  8034. method:"POST",
  8035. dataType: "json",
  8036. success: function (recvData)
  8037. {
  8038. self.RecvLatestData(recvData);
  8039. self.Execute.RunNextJob();
  8040. },
  8041. error: function(request)
  8042. {
  8043. self.RecvError(request);
  8044. }
  8045. });
  8046. }
  8047. this.RecvLatestData = function (recvData)
  8048. {
  8049. let data=recvData.data;
  8050. if (data.ver==2.0)
  8051. {
  8052. this.RecvLatestDataVer2(data);
  8053. return;
  8054. }
  8055. if (!data.stock || data.stock.length!=1) return;
  8056. let stock=data.stock[0];
  8057. if (!stock) return;
  8058. if (IFrameSplitOperator.IsNumber(stock.yclose)) this.LatestData.set(DYNAINFO_ARGUMENT_ID.YCLOSE,stock.yclose);
  8059. if (IFrameSplitOperator.IsNumber(stock.open)) this.LatestData.set(DYNAINFO_ARGUMENT_ID.OPEN,stock.open);
  8060. if (IFrameSplitOperator.IsNumber(stock.high)) this.LatestData.set(DYNAINFO_ARGUMENT_ID.HIGH,stock.high);
  8061. if (IFrameSplitOperator.IsNumber(stock.low)) this.LatestData.set(DYNAINFO_ARGUMENT_ID.LOW,stock.low);
  8062. if (IFrameSplitOperator.IsNumber(stock.price)) this.LatestData.set(DYNAINFO_ARGUMENT_ID.CLOSE,stock.price);
  8063. if (IFrameSplitOperator.IsNumber(stock.vol)) this.LatestData.set(DYNAINFO_ARGUMENT_ID.VOL,stock.vol);
  8064. if (IFrameSplitOperator.IsNumber(stock.amount)) this.LatestData.set(DYNAINFO_ARGUMENT_ID.AMOUNT,stock.amount);
  8065. if (IFrameSplitOperator.IsNumber(stock.increase)) this.LatestData.set(DYNAINFO_ARGUMENT_ID.INCREASE,stock.increase);
  8066. if (IFrameSplitOperator.IsNumber(stock.exchangerate)) this.LatestData.set(DYNAINFO_ARGUMENT_ID.EXCHANGERATE,stock.exchangerate);
  8067. if (IFrameSplitOperator.IsNumber(stock.amplitude)) this.LatestData.set(DYNAINFO_ARGUMENT_ID.AMPLITUDE,stock.amplitude);
  8068. /*
  8069. this.LatestData={ Symbol:stock.symbol, Name:stock.name, Date:stock.date, Time:stock.time,
  8070. YClose:stock.yclose,Price:stock.price, Open:stock.open, High:stock.high, Low:stock.low, Vol:stock.vol, Amount:stock.amount,
  8071. Increase:stock.increase, Exchangerate:stock.exchangerate, Amplitude:stock.amplitude};
  8072. */
  8073. JSConsole.Complier.Log('[JSSymbolData::RecvLatestData] symbol, LatestData', stock.symbol, this.LatestData);
  8074. }
  8075. //data:[{ id:, value: }]
  8076. this.RecvLatestDataVer2=function(recvData)
  8077. {
  8078. let data=recvData.data;
  8079. if (!IFrameSplitOperator.IsNonEmptyArray(data.data)) return;
  8080. var symbol=data.symbol;
  8081. for(var i=0;i<data.data.length;++i)
  8082. {
  8083. var item=data.data[i];
  8084. if (!item) continue;
  8085. if (!IFrameSplitOperator.IsNumber(item.id)) continue;
  8086. if (IFrameSplitOperator.IsNumber(item.value) || IFrameSplitOperator.IsString(item.value))
  8087. {
  8088. JSConsole.Complier.Log(`[JSSymbolData::RecvLatestDataVer2] symbol=${symbol} DYNAINFO(${item.id})=${item.value}.`);
  8089. this.LatestData.set(item.id, item.value);
  8090. }
  8091. }
  8092. JSConsole.Complier.Log('[JSSymbolData::RecvLatestDataVer2]', this.LatestData);
  8093. }
  8094. this.GetLatestCacheData=function(dataname)
  8095. {
  8096. if (this.LatestData && this.LatestData.has(dataname)) return this.LatestData.get(dataname);
  8097. return null;
  8098. }
  8099. this.GetVolRateData = function (job, node)
  8100. {
  8101. var volrKey = job.ID.toString() + '-VolRate-' + this.Symbol;
  8102. if (this.ExtendData.has(volrKey)) return this.Execute.RunNextJob();
  8103. var self=this;
  8104. var dayCount=30;
  8105. if (this.NetworkFilter)
  8106. {
  8107. var dateRange=this.Data.GetDateRange();
  8108. var dayCount=1;
  8109. if (this.DataType==HQ_DATA_TYPE.MULTIDAY_MINUTE_ID) dayCount=this.DayCount;
  8110. var obj=
  8111. {
  8112. Name:'JSSymbolData::GetVolRateData', //类名:: 函数
  8113. Explain:'分时量比数据(成交量)',
  8114. Request:
  8115. {
  8116. Url:self.KLineApiUrl, Type:'POST' ,
  8117. Data: { symbol:self.Symbol, dayCount:dayCount, field: ["name","symbol","vol"], period:0, right:0, dateRange:dateRange }
  8118. },
  8119. Self:this,
  8120. PreventDefault:false
  8121. };
  8122. this.NetworkFilter(obj, function(recvData)
  8123. {
  8124. self.RecvVolRateData(recvData,volrKey);
  8125. self.Execute.RunNextJob();
  8126. });
  8127. if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求
  8128. }
  8129. JSNetwork.HttpRequest({
  8130. url: self.KLineApiUrl,
  8131. data:
  8132. {
  8133. "field": ["name","symbol","vol"],
  8134. "symbol": self.Symbol,
  8135. "start": -1,
  8136. "count": dayCount
  8137. },
  8138. type:"post",
  8139. dataType: "json",
  8140. async:true,
  8141. success: function (recvData)
  8142. {
  8143. self.RecvVolRateData(recvData,volrKey);
  8144. self.Execute.RunNextJob();
  8145. },
  8146. error: function(request)
  8147. {
  8148. self.RecvError(request);
  8149. }
  8150. });
  8151. }
  8152. this.RecvVolRateData = function (recvData, key)
  8153. {
  8154. var data=recvData.data;
  8155. var sumVol=0,avgVol5=0;
  8156. var mapAvgVol5=new Map();
  8157. if (data.Ver==2.0) // {Ver:2.0 , data:[ [日期,5日vol均值]] }
  8158. {
  8159. if (!IFrameSplitOperator.IsNonEmptyArray(data.data)) return;
  8160. for(var i=0;i<data.data.length;++i)
  8161. {
  8162. var item=data.data[i];
  8163. if (!IFrameSplitOperator.IsNonEmptyArray(item)) continue;
  8164. if (item.length<2) continue;
  8165. if (IFrameSplitOperator.IsNumber(item[0]) && IFrameSplitOperator.IsPlusNumber(item[1]))
  8166. {
  8167. mapAvgVol5.set(item[0],{ AvgVol5:item[1] } );
  8168. }
  8169. }
  8170. }
  8171. else
  8172. {
  8173. if (!IFrameSplitOperator.IsNonEmptyArray(data.data)) return;
  8174. var minuteCount=241;
  8175. if (IFrameSplitOperator.IsNumber(data.minutecount)) minuteCount=data.minutecount;
  8176. for(var i=0,j=0,dayCount=0;i<data.data.length;++i) //每天的5日成交均量
  8177. {
  8178. sumVol=0;
  8179. for(j=i,dayCount=0;j>=0 && dayCount<5;--j, ++dayCount)
  8180. {
  8181. var item=data.data[j];
  8182. if (IFrameSplitOperator.IsNumber(item[6]))
  8183. sumVol+=item[6];
  8184. }
  8185. if (dayCount>0)
  8186. {
  8187. avgVol5=sumVol/dayCount/minuteCount;
  8188. var item=data.data[i];
  8189. mapAvgVol5.set(item[0],
  8190. {
  8191. //for debug
  8192. //Vol5:sumVol, MinuteCount:minuteCount,,Count:dayCount,
  8193. AvgVol5:avgVol5
  8194. } );
  8195. }
  8196. }
  8197. }
  8198. if (mapAvgVol5.size>0) this.ExtendData.set(key,mapAvgVol5);
  8199. JSConsole.Complier.Log('[JSSymbolData::RecvVolRateData]', mapAvgVol5);
  8200. }
  8201. this.GetVolRateCacheData=function(node)
  8202. {
  8203. var key=JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_VOLR_DATA.toString()+'-VolRate-'+this.Symbol;
  8204. if (!key || !this.ExtendData.has(key)) this.Execute.ThrowUnexpectedNode(node,'不支持VOLR');
  8205. var result=[];
  8206. var mapAvgVol5=this.ExtendData.get(key);
  8207. var totalVol=0, preDate=0, avgVol5=null;
  8208. for(var i=0, j=0;i<this.Data.Data.length;++i)
  8209. {
  8210. result[i]=null;
  8211. var item=this.Data.Data[i];
  8212. if (preDate!=item.Date)
  8213. {
  8214. avgVol5=null;
  8215. j=0;
  8216. totalVol=0;
  8217. if (mapAvgVol5.has(item.Date))
  8218. {
  8219. var volItem=mapAvgVol5.get(item.Date);
  8220. avgVol5=volItem.AvgVol5;
  8221. }
  8222. preDate=item.Date;
  8223. }
  8224. if (avgVol5==null) continue;
  8225. totalVol+=item.Vol;
  8226. result[i]=totalVol/(j+1)/avgVol5*100;
  8227. ++j;
  8228. }
  8229. return result;
  8230. }
  8231. this.GetOtherSymbolParam=function(name)
  8232. {
  8233. var args=name.split("$");
  8234. var setStockDataName=new Set(['CLOSE',"C",'VOL','V','OPEN','O','HIGH','H','LOW','L','AMOUNT','AMO','VOLINSTK']);
  8235. if (!setStockDataName.has(args[1])) return null;
  8236. var symbol=args[0];
  8237. if (symbol.length==6)
  8238. {
  8239. if (symbol[0]=="6" || symbol[0]=="5" || symbol[0]=="8" || symbol[0]=="9")
  8240. symbol+=".SH";
  8241. else if (symbol[0]=='0' || symbol[0]=='1' || symbol[0]=='2' || symbol[0]=='3')
  8242. symbol+='.SZ';
  8243. }
  8244. else if (symbol.indexOf("SZ")==0)
  8245. {
  8246. symbol=symbol.substr(2)+".SZ";
  8247. }
  8248. else if (symbol.indexOf("SH")==0)
  8249. {
  8250. symbol=symbol.substr(2)+".SH";
  8251. }
  8252. else if (symbol.indexOf("_")>0)
  8253. {
  8254. var arySymbol=symbol.split("_");
  8255. symbol=`${arySymbol[1]}.${arySymbol[0]}`;
  8256. }
  8257. else
  8258. return null;
  8259. return { Symbol:symbol.toLowerCase(), DataName:args[1] };
  8260. }
  8261. //获取其他股票数据
  8262. this.GetOtherSymbolData=function(job)
  8263. {
  8264. var symbol=this.Symbol;
  8265. if (job.Literal)
  8266. {
  8267. var args=this.GetOtherSymbolParam(job.Literal.toUpperCase());
  8268. if (!args)
  8269. {
  8270. var token=job.Token;
  8271. this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`${job.Literal} Error.`);
  8272. }
  8273. symbol=args.Symbol;
  8274. }
  8275. else
  8276. {
  8277. var args=job.Args;
  8278. if (args.length>0)
  8279. {
  8280. var item=args[0];
  8281. if (item.Type==Syntax.Literal)
  8282. {
  8283. symbol=item.Value;
  8284. }
  8285. else if (item.Type==Syntax.Identifier) //变量 !!只支持默认的变量值
  8286. {
  8287. var isFind=false;
  8288. for(var j in this.Arguments)
  8289. {
  8290. const argItem=this.Arguments[j];
  8291. if (argItem.Name==item.Name)
  8292. {
  8293. symbol=argItem.Value;
  8294. isFind=true;
  8295. break;
  8296. }
  8297. }
  8298. if (!isFind)
  8299. {
  8300. var token=job.Token;
  8301. this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`${job.FunctionName}() Error: can't read ${item.Name}`);
  8302. }
  8303. }
  8304. }
  8305. }
  8306. job.Symbol=symbol.toLowerCase();
  8307. if (job.Symbol==this.Symbol) return this.Execute.RunNextJob();
  8308. if (this.OtherSymbolData.has(job.Symbol)) return this.Execute.RunNextJob();
  8309. var self=this;
  8310. if (this.DataType==HQ_DATA_TYPE.KLINE_ID && ChartData.IsDayPeriod(this.Period,true)) //请求日线数据
  8311. {
  8312. if (this.NetworkFilter)
  8313. {
  8314. var dateRange=this.Data.GetDateRange();
  8315. var obj=
  8316. {
  8317. Name:'JSSymbolData::GetOtherSymbolData', //类名::函数名
  8318. Explain:'指定个股数据',
  8319. Request:
  8320. {
  8321. Data:
  8322. {
  8323. symbol:job.Symbol,
  8324. right:self.Right,
  8325. period:self.Period,
  8326. dateRange:dateRange
  8327. }
  8328. },
  8329. Self:this,
  8330. PreventDefault:false
  8331. };
  8332. this.NetworkFilter(obj, function(data)
  8333. {
  8334. self.RecvOtherSymbolKData(data,job);
  8335. self.Execute.RunNextJob();
  8336. });
  8337. if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求
  8338. }
  8339. JSNetwork.HttpRequest({
  8340. url: self.KLineApiUrl,
  8341. data:
  8342. {
  8343. "field": [ "name", "symbol","yclose","open","price","high","low","vol"],
  8344. "symbol": job.Symbol,
  8345. "start": -1,
  8346. "count": self.MaxRequestDataCount+500 //多请求2年的数据 确保股票剔除停牌日期以后可以对上
  8347. },
  8348. method: "POST",
  8349. dataType: "json",
  8350. async:true,
  8351. success: function (recvData)
  8352. {
  8353. self.RecvOtherSymbolKDayData(recvData,job);
  8354. self.Execute.RunNextJob();
  8355. },
  8356. error: function(request)
  8357. {
  8358. self.RecvError(request);
  8359. }
  8360. });
  8361. }
  8362. else if (ChartData.IsMinutePeriod(this.Period, true) || this.DataType==HQ_DATA_TYPE.MINUTE_ID || this.DataType==HQ_DATA_TYPE.MULTIDAY_MINUTE_ID) //请求分钟数据
  8363. {
  8364. if (this.NetworkFilter)
  8365. {
  8366. var dateRange=this.Data.GetDateRange();
  8367. var obj=
  8368. {
  8369. Name:'JSSymbolData::GetOtherSymbolData', //类名::函数名
  8370. Explain:'指定个股数据',
  8371. Request:
  8372. {
  8373. Data:
  8374. {
  8375. symbol:job.Symbol,
  8376. right:self.Right,
  8377. period:self.Period,
  8378. dateRange:dateRange
  8379. }
  8380. },
  8381. Self:this,
  8382. PreventDefault:false
  8383. };
  8384. this.NetworkFilter(obj, function(data)
  8385. {
  8386. self.RecvOtherSymbolKData(data,job);
  8387. self.Execute.RunNextJob();
  8388. });
  8389. if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求
  8390. }
  8391. JSNetwork.HttpRequest({
  8392. url: self.MinuteKLineApiUrl,
  8393. data:
  8394. {
  8395. "field": ["name","symbol","yclose","open","price","high","low","vol"],
  8396. "symbol": job.Symbol,
  8397. "start": -1,
  8398. "count": self.MaxRequestMinuteDayCount+5
  8399. },
  8400. method: "POST",
  8401. dataType: "json",
  8402. async:true,
  8403. success: function (data)
  8404. {
  8405. self.RecvOtherSymbolKMinuteData(data,job);
  8406. self.Execute.RunNextJob();
  8407. },
  8408. error: function(request)
  8409. {
  8410. self.RecvError(request);
  8411. }
  8412. });
  8413. }
  8414. }
  8415. //第3方数据对接
  8416. this.RecvOtherSymbolKData=function(recvData,job)
  8417. {
  8418. var data=recvData.data;
  8419. JSConsole.Complier.Log('[JSSymbolData::RecvOtherSymbolKData] recv data' , data);
  8420. var kData=new ChartData();
  8421. var hisData=null;
  8422. var period=this.Period;
  8423. if (this.DataType==HQ_DATA_TYPE.KLINE_ID && ChartData.IsDayPeriod(this.Period,true)) //日线数据
  8424. {
  8425. hisData=this.JsonDataToHistoryData(data);
  8426. kData.DataType=0;
  8427. }
  8428. else //分钟线数据
  8429. {
  8430. hisData=this.JsonDataToMinuteHistoryData(data);
  8431. kData.DataType=1;
  8432. //走势图使用1分钟K线模式
  8433. if (this.DataType==HQ_DATA_TYPE.MINUTE_ID || this.DataType==HQ_DATA_TYPE.MULTIDAY_MINUTE_ID)
  8434. period=4;
  8435. }
  8436. kData.Period=this.Period;
  8437. kData.Right=this.Right;
  8438. kData.Data=this.Data.FixKData(hisData,period);
  8439. this.OtherSymbolData.set(job.Symbol, kData);
  8440. }
  8441. this.RecvOtherSymbolKDayData=function(recvData,job)
  8442. {
  8443. var data=recvData.data;
  8444. JSConsole.Complier.Log('[JSSymbolData::RecvOtherSymbolKDayData] recv data' , data);
  8445. let hisData=this.JsonDataToHistoryData(data);
  8446. var kData=new ChartData();
  8447. kData.DataType=0; //日线数据
  8448. kData.Data=hisData;
  8449. var aryOverlayData=this.SourceData.GetOverlayData(kData.Data); //和主图数据拟合以后的数据
  8450. kData.Data=aryOverlayData;
  8451. if (ChartData.IsDayPeriod(this.Period,false)) //周期数据
  8452. {
  8453. let periodData=kData.GetPeriodData(this.Period);
  8454. kData.Data=periodData;
  8455. }
  8456. this.OtherSymbolData.set(job.Symbol, kData);
  8457. }
  8458. this.RecvOtherSymbolKMinuteData=function(recvData, job)
  8459. {
  8460. var data=recvData.data;
  8461. JSConsole.Complier.Log('[JSSymbolData::RecvOtherSymbolKMinuteData] recv data' , data);
  8462. let hisData=this.JsonDataToMinuteHistoryData(data);
  8463. var kData=new ChartData();
  8464. kData.DataType=1; /*分钟线数据 */
  8465. kData.Data=hisData;
  8466. if (ChartData.IsMinutePeriod(this.Period,false)) //周期数据
  8467. {
  8468. let periodData=kData.GetPeriodData(this.Period);
  8469. kData.Data=periodData;
  8470. }
  8471. this.OtherSymbolData.set(job.Symbol, kData);
  8472. }
  8473. this.GetOtherSymolCacheData=function(obj)
  8474. {
  8475. var symbol,dataName;
  8476. if (obj.FunctionName)
  8477. {
  8478. dataName=obj.FunctionName;
  8479. var args=obj.Args;
  8480. if (args.length<=0) return this.GetSymbolCacheData(dataName);
  8481. symbol=args[0].toString().toLowerCase();
  8482. }
  8483. else if (obj.Literal)
  8484. {
  8485. var args=this.GetOtherSymbolParam(obj.Literal.toUpperCase());
  8486. if (!args) return [];
  8487. symbol=args.Symbol;
  8488. dataName=args.DataName;
  8489. }
  8490. if (symbol==this.Symbol) return this.GetSymbolCacheData(dataName);
  8491. if (!this.OtherSymbolData.has(symbol)) return [];
  8492. var kData=this.OtherSymbolData.get(symbol);
  8493. var upperSymbol=symbol.toUpperCase();
  8494. switch(dataName)
  8495. {
  8496. case 'CLOSE':
  8497. case 'C':
  8498. return kData.GetClose();
  8499. case 'VOL':
  8500. case 'V':
  8501. if (MARKET_SUFFIX_NAME.IsSHSZ(upperSymbol))
  8502. return kData.GetVol(100); //A股的 把股转成手
  8503. return kData.GetVol();
  8504. case 'OPEN':
  8505. case 'O':
  8506. return kData.GetOpen();
  8507. case 'HIGH':
  8508. case 'H':
  8509. return kData.GetHigh();
  8510. case 'LOW':
  8511. case 'L':
  8512. return kData.GetLow();
  8513. case 'AMOUNT':
  8514. case 'AMO':
  8515. return kData.GetAmount();
  8516. case 'VOLINSTK':
  8517. return kData.GetPosition();
  8518. }
  8519. }
  8520. //获取大盘指数数据
  8521. this.GetIndexData=function()
  8522. {
  8523. if (this.IndexData) return this.Execute.RunNextJob();
  8524. var self=this;
  8525. if (JSCommonData.ChartData.IsDayPeriod(this.Period,true)) //请求日线数据
  8526. {
  8527. JSNetwork.HttpRequest({
  8528. url: self.KLineApiUrl,
  8529. data:
  8530. {
  8531. "field": ["name", "symbol", "yclose", "open", "price", "high", "low", "vol", 'up', 'down', 'stop', 'unchanged'],
  8532. "symbol": '000001.sh',
  8533. "start": -1,
  8534. "count": self.MaxRequestDataCount+500 //多请求2年的数据 确保股票剔除停牌日期以后可以对上
  8535. },
  8536. method: 'POST',
  8537. dataType: "json",
  8538. success: function (recvData)
  8539. {
  8540. self.RecvIndexHistroyData(recvData);
  8541. self.Execute.RunNextJob();
  8542. },
  8543. error: function(request)
  8544. {
  8545. self.RecvError(request);
  8546. }
  8547. });
  8548. }
  8549. else if (JSCommonData.ChartData.IsMinutePeriod(this.Period, true)) //请求分钟数据
  8550. {
  8551. JSNetwork.HttpRequest({
  8552. url: self.MinuteKLineApiUrl,
  8553. data:
  8554. {
  8555. "field": ["name","symbol","yclose","open","price","high","low","vol"],
  8556. "symbol": '000001.sh',
  8557. "start": -1,
  8558. "count": self.MaxRequestMinuteDayCount+5
  8559. },
  8560. method: 'POST',
  8561. dataType: "json",
  8562. success: function (data)
  8563. {
  8564. self.RecvIndexMinuteHistroyData(data);
  8565. self.Execute.RunNextJob();
  8566. },
  8567. error: function(request)
  8568. {
  8569. self.RecvError(request);
  8570. }
  8571. });
  8572. }
  8573. }
  8574. this.RecvIndexHistroyData=function(recvData)
  8575. {
  8576. let data = recvData.data;
  8577. JSConsole.Complier.Log('[JSSymbolData::RecvIndexHistroyData] recv data' , data);
  8578. let hisData=this.JsonDataToHistoryData(data);
  8579. this.IndexData = new JSCommonData.ChartData();
  8580. this.IndexData.DataType=0; /*日线数据 */
  8581. this.IndexData.Data=hisData;
  8582. var aryOverlayData = this.SourceData.GetOverlayData(this.IndexData.Data); //和主图数据拟合以后的数据
  8583. this.IndexData.Data=aryOverlayData;
  8584. if (JSCommonData.ChartData.IsDayPeriod(this.Period, false)) //周期数据
  8585. {
  8586. let periodData=this.IndexData.GetPeriodData(this.Period);
  8587. this.IndexData.Data=periodData;
  8588. }
  8589. }
  8590. this.RecvIndexMinuteHistroyData = function (recvData)
  8591. {
  8592. let data = recvData.data;
  8593. JSConsole.Complier.Log('[JSSymbolData::RecvIndexMinuteHistroyData] recv data' , data);
  8594. let hisData=this.JsonDataToMinuteHistoryData(data);
  8595. this.IndexData = new JSCommonData.ChartData();
  8596. this.IndexData.DataType=1; /*分钟线数据 */
  8597. this.IndexData.Data=hisData;
  8598. if (JSCommonData.ChartData.IsMinutePeriod(this.Period, false)) //周期数据
  8599. {
  8600. let periodData=this.IndexData.GetPeriodData(this.Period);
  8601. this.IndexData.Data=periodData;
  8602. }
  8603. }
  8604. //获取大盘指数缓存数据
  8605. this.GetIndexCacheData=function(dataName)
  8606. {
  8607. if (!this.IndexData) return new Array();
  8608. switch(dataName)
  8609. {
  8610. case 'INDEXA':
  8611. return this.IndexData.GetAmount();
  8612. case 'INDEXC':
  8613. return this.IndexData.GetClose();
  8614. case 'INDEXH':
  8615. return this.IndexData.GetHigh();
  8616. case 'INDEXL':
  8617. return this.IndexData.GetLow();
  8618. case 'INDEXO':
  8619. return this.IndexData.GetOpen();
  8620. case 'INDEXV':
  8621. return this.IndexData.GetVol();
  8622. case 'INDEXADV':
  8623. return this.IndexData.GetUp();
  8624. case 'INDEXDEC':
  8625. return this.IndexData.GetDown();
  8626. }
  8627. }
  8628. //分钟涨幅股票个数统计数据下载
  8629. this.GetIndexIncreaseData = function (job)
  8630. {
  8631. var upKey = job.ID.toString() + '-UpCount-' + job.Symbol;
  8632. var downKey = job.ID.toString() + '-DownCount-' + job.Symbol;
  8633. if (this.ExtendData.has(upKey) && this.ExtendData.has(downKey)) return this.Execute.RunNextJob();
  8634. var symbol = job.Symbol;
  8635. symbol = symbol.replace('.CI', '.ci');
  8636. var self = this;
  8637. var apiUrl = g_JSComplierResource.CacheDomain + '/cache/analyze/increaseanalyze/' + symbol + '.json';
  8638. JSConsole.Complier.Log('[JSSymbolData::GetIndexIncreaseData] Get url=', apiUrl);
  8639. JSNetwork.HttpRequest({
  8640. url: apiUrl,
  8641. method: "GET",
  8642. dataType: "json",
  8643. success: function (data)
  8644. {
  8645. self.RecvMinuteIncreaseData(data, { UpKey: upKey, DownKey: downKey });
  8646. self.Execute.RunNextJob();
  8647. },
  8648. error: function (request)
  8649. {
  8650. self.RecvError(request);
  8651. }
  8652. });
  8653. }
  8654. this.RecvMinuteIncreaseData = function (recvData, key)
  8655. {
  8656. JSConsole.Complier.Log('[JSSymbolData::RecvMinuteIncreaseData] recv data', recvData);
  8657. var data=recvData.data;
  8658. if (!data.minute) return;
  8659. var minuteData = data.minute;
  8660. if (!minuteData.time || !minuteData.up || !minuteData.down) return;
  8661. var upData = [], downData = [];
  8662. for (var i = 0; i < minuteData.time.length; ++i) {
  8663. upData[i] = minuteData.up[i];
  8664. downData[i] = minuteData.down[i];
  8665. }
  8666. this.ExtendData.set(key.UpKey, upData);
  8667. this.ExtendData.set(key.DownKey, downData);
  8668. }
  8669. //分钟涨幅股票个数统计数据
  8670. this.GetIndexIncreaseCacheData = function (funcName, symbol, node) {
  8671. var key;
  8672. if (funcName == 'UPCOUNT') key = JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_INDEX_INCREASE_DATA.toString() + '-UpCount-' + symbol;
  8673. else if (funcName == 'DOWNCOUNT') key = JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_INDEX_INCREASE_DATA.toString() + '-DownCount-' + symbol;
  8674. if (!key || !this.ExtendData.has(key)) this.Execute.ThrowUnexpectedNode(node, '不支持函数' + funcName + '(' + symbol + ')');
  8675. return this.ExtendData.get(key);
  8676. }
  8677. this.GetSymbolData=function()
  8678. {
  8679. if (this.Data) return this.Execute.RunNextJob();
  8680. let self=this;
  8681. if (this.DataType === 2) //当天分钟数据
  8682. {
  8683. JSNetwork.HttpRequest({
  8684. url: self.RealtimeApiUrl,
  8685. data:
  8686. {
  8687. "field": ["name", "symbol", "yclose", "open", "price", "high", "low", "vol", "amount", "date", "minute", "time", "minutecount"],
  8688. "symbol": [self.Symbol],
  8689. "start": -1
  8690. },
  8691. method: 'POST',
  8692. dataType: "json",
  8693. async: true,
  8694. success: function (recvData) {
  8695. self.RecvMinuteData(recvData);
  8696. self.Execute.RunNextJob();
  8697. }
  8698. });
  8699. return;
  8700. }
  8701. if (JSCommonData.ChartData.IsDayPeriod(this.Period,true)) //请求日线数据
  8702. {
  8703. if (this.NetworkFilter)
  8704. {
  8705. var obj=
  8706. {
  8707. Name:'JSSymbolData::GetSymbolData',
  8708. Explain:"日线数据",
  8709. Request:
  8710. { Url:self.RealtimeApiUrl, Type:'POST' ,
  8711. Data:
  8712. {
  8713. "field": [ "name", "symbol","yclose","open","price","high","low","vol"],
  8714. "symbol": self.Symbol,
  8715. "start": -1,
  8716. "count": self.MaxRequestDataCount,
  8717. "period":this.Period,
  8718. "right":this.Right
  8719. }
  8720. },
  8721. Self:this,
  8722. PreventDefault:false
  8723. };
  8724. if (this.KLineDateTimeRange)
  8725. {
  8726. obj.Request.KLineDataTimeRange={Start:{ Date:this.KLineDateTimeRange.Start.Date}, End:{ Date:this.KLineDateTimeRange.End.Date} };
  8727. if (this.IsNumber(this.KLineDateTimeRange.Start.Time)) obj.Request.KLineDataTimeRange.Start.Time=this.KLineDateTimeRange.Start.Time;
  8728. if (this.IsNumber(this.KLineDateTimeRange.End.Time)) obj.Request.KLineDataTimeRange.End.Time=this.KLineDateTimeRange.End.Time;
  8729. }
  8730. this.NetworkFilter(obj, function(data)
  8731. {
  8732. self.RecvHistroyData(data);
  8733. self.Execute.RunNextJob();
  8734. });
  8735. if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求
  8736. }
  8737. JSNetwork.HttpRequest({
  8738. url: self.KLineApiUrl,
  8739. data:
  8740. {
  8741. "field": [ "name", "symbol","yclose","open","price","high","low","vol"],
  8742. "symbol": self.Symbol,
  8743. "start": -1,
  8744. "count": self.MaxRequestDataCount
  8745. },
  8746. method: 'POST',
  8747. dataType: "json",
  8748. async:true,
  8749. success: function (recvData)
  8750. {
  8751. self.RecvHistroyData(recvData);
  8752. self.Execute.RunNextJob();
  8753. },
  8754. error: function(request)
  8755. {
  8756. self.RecvError(request);
  8757. }
  8758. });
  8759. }
  8760. else if (JSCommonData.ChartData.IsMinutePeriod(this.Period, true)) //请求分钟数据
  8761. {
  8762. if (this.NetworkFilter)
  8763. {
  8764. var obj=
  8765. {
  8766. Name:'JSSymbolData::GetSymbolData',
  8767. Explain:"分钟K线数据",
  8768. Request:
  8769. { Url:self.MinuteKLineApiUrl, Type:'POST' ,
  8770. Data:
  8771. {
  8772. "field": ["name","symbol","yclose","open","price","high","low","vol"],
  8773. "symbol": self.Symbol,
  8774. "start": -1,
  8775. "count": self.MaxRequestMinuteDayCount,
  8776. "period":this.Period,
  8777. "right":this.Right
  8778. }
  8779. },
  8780. Self:this,
  8781. PreventDefault:false
  8782. };
  8783. if (this.KLineDateTimeRange)
  8784. {
  8785. obj.Request.KLineDataTimeRange={Start:{ Date:this.KLineDateTimeRange.Start.Date}, End:{ Date:this.KLineDateTimeRange.End.Date} };
  8786. if (this.IsNumber(this.KLineDateTimeRange.Start.Time)) obj.Request.KLineDataTimeRange.Start.Time=this.KLineDateTimeRange.Start.Time;
  8787. if (this.IsNumber(this.KLineDateTimeRange.End.Time)) obj.Request.KLineDataTimeRange.End.Time=this.KLineDateTimeRange.End.Time;
  8788. }
  8789. this.NetworkFilter(obj, function(data)
  8790. {
  8791. self.RecvMinuteHistroyData(data);
  8792. self.Execute.RunNextJob();
  8793. });
  8794. if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求
  8795. }
  8796. JSNetwork.HttpRequest({
  8797. url: this.MinuteKLineApiUrl,
  8798. data:
  8799. {
  8800. "field": ["name","symbol","yclose","open","price","high","low","vol"],
  8801. "symbol": self.Symbol,
  8802. "start": -1,
  8803. "count": self.MaxRequestMinuteDayCount
  8804. },
  8805. method: 'POST',
  8806. dataType: "json",
  8807. async:true,
  8808. success: function (data)
  8809. {
  8810. self.RecvMinuteHistroyData(data);
  8811. self.Execute.RunNextJob();
  8812. },
  8813. error: function(request)
  8814. {
  8815. self.RecvError(request);
  8816. }
  8817. });
  8818. }
  8819. }
  8820. this.RecvHistroyData=function(recvData)
  8821. {
  8822. let data=recvData.data;
  8823. JSConsole.Complier.Log('[JSSymbolData::RecvHistroyData] recv data' , data);
  8824. let hisData=this.JsonDataToHistoryData(data);
  8825. this.Data=new JSCommonData.ChartData();
  8826. this.Data.DataType=0; /*日线数据 */
  8827. this.Data.Data=hisData;
  8828. this.SourceData = new JSCommonData.ChartData;
  8829. this.SourceData.Data = hisData;
  8830. if (this.IsApiPeriod) //后台周期 前端不处理
  8831. {
  8832. }
  8833. else
  8834. {
  8835. if (this.Right>0) //复权
  8836. {
  8837. let rightData=this.Data.GetRightDate(this.Right);
  8838. this.Data.Data=rightData;
  8839. }
  8840. if (JSCommonData.ChartData.IsDayPeriod(this.Period, false)) //周期数据
  8841. {
  8842. let periodData=this.Data.GetPeriodData(this.Period);
  8843. this.Data.Data=periodData;
  8844. }
  8845. }
  8846. this.Data.Right=this.Right;
  8847. this.Data.Period=this.Period;
  8848. this.Name = data.name;
  8849. }
  8850. this.RecvMinuteHistroyData = function (recvData)
  8851. {
  8852. let data = recvData.data;
  8853. JSConsole.Complier.Log('[JSSymbolData::RecvMinuteHistroyData] recv data' , data);
  8854. let hisData=this.JsonDataToMinuteHistoryData(data);
  8855. this.Data = new JSCommonData.ChartData();
  8856. this.Data.DataType=1; /*分钟线数据 */
  8857. this.Data.Data=hisData;
  8858. this.SourceData = new JSCommonData.ChartData;
  8859. this.SourceData.Data = hisData;
  8860. if (this.IsApiPeriod) //后台周期 前端不处理
  8861. {
  8862. }
  8863. else
  8864. {
  8865. if (JSCommonData.ChartData.IsMinutePeriod(this.Period, false)) //周期数据
  8866. {
  8867. let periodData=this.Data.GetPeriodData(this.Period);
  8868. this.Data.Data=periodData;
  8869. }
  8870. }
  8871. this.Data.Period=this.Period;
  8872. this.Name = data.name;
  8873. }
  8874. //最新的分钟数据走势图
  8875. this.RecvMinuteData = function (recvData)
  8876. {
  8877. let data = recvData.data;
  8878. JSConsole.Complier.Log('[JSSymbolData::RecvMinuteData] recv data', data);
  8879. var aryMinuteData = this.JsonDataToMinuteData(data);
  8880. this.Data = new JSCommonData.ChartData();
  8881. this.Data.DataType = 2; /*分钟走势图数据 */
  8882. this.Data.Data = aryMinuteData;
  8883. this.Name = data.stock[0].name;
  8884. }
  8885. this.GetSymbolCacheData=function(dataName)
  8886. {
  8887. if (!this.Data) return new Array();
  8888. var upperSymbol=this.Symbol.toUpperCase();
  8889. switch(dataName)
  8890. {
  8891. case 'CLOSE':
  8892. case 'C':
  8893. return this.Data.GetClose();
  8894. case 'VOL':
  8895. case 'V':
  8896. if (MARKET_SUFFIX_NAME.IsSHSZ(upperSymbol) && this.DataType==HQ_DATA_TYPE.KLINE_ID) //!! A股K线量单位时股,分时图单位还是手
  8897. return this.Data.GetVol(100); //A股的 把股转成手
  8898. return this.Data.GetVol();
  8899. case 'OPEN':
  8900. case 'O':
  8901. return this.Data.GetOpen();
  8902. case 'HIGH':
  8903. case 'H':
  8904. return this.Data.GetHigh();
  8905. case 'LOW':
  8906. case 'L':
  8907. return this.Data.GetLow();
  8908. case 'AMOUNT':
  8909. case 'AMO':
  8910. return this.Data.GetAmount();
  8911. case "OPI": //文华 持仓量
  8912. case 'VOLINSTK':
  8913. return this.Data.GetPosition();
  8914. case "ZSTJJ": //均价
  8915. return this.Data.GetAvPrice();
  8916. case "SETTLE": //文华 结算价
  8917. case "QHJSJ": //通达信 结算价
  8918. return this.Data.GetSettlementPrice(); //结算价
  8919. case "ISEQUAL": //平盘
  8920. return this.Data.GetIsEqual();
  8921. case "ISUP": //收阳
  8922. return this.Data.GetIsUp();
  8923. case "ISDOWN": //收阴
  8924. return this.Data.GetIsDown();
  8925. }
  8926. }
  8927. this.GetCurrBarsCount=function()
  8928. {
  8929. if (!this.Data || !this.Data.Data || !this.Data.Data.length) return new Array();
  8930. let lCount=this.Data.Data.length;
  8931. let result=[];
  8932. for(let i=lCount-1;i>=0;--i)
  8933. result.push(i);
  8934. return result;
  8935. }
  8936. this.GetTotalBarsCount=function()
  8937. {
  8938. let lCount=this.Data.Data.length;
  8939. return lCount;
  8940. }
  8941. this.GetTotalTradeMinuteCount=function()
  8942. {
  8943. var data=g_MinuteCoordinateData.GetCoordinateData(this.Symbol);
  8944. if (data && data.Count>0) return data.Count-1;
  8945. return 242;
  8946. }
  8947. //BARPOS 返回从第一根K线开始到当前的周期数。
  8948. //注:
  8949. //1、BARPOS返回本地已有的K线根数,从本机上存在的数据开始算起。
  8950. //2、本机已有的第一根K线上返回值为1。
  8951. this.GetBarPos=function()
  8952. {
  8953. let result=[];
  8954. if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result;
  8955. let lCount=this.Data.Data.length;
  8956. for(let i=0;i<lCount;++i)
  8957. result.push(i+1);
  8958. return result;
  8959. }
  8960. this.GetIsLastBar = function ()
  8961. {
  8962. let result = [];
  8963. if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result
  8964. let lCount = this.Data.Data.length;
  8965. for (let i = 0; i < lCount; ++i)
  8966. {
  8967. if (i == lCount - 1) result.push(1);
  8968. else result.push(0);
  8969. }
  8970. return result;
  8971. }
  8972. //BARSTATUS返回数据位置信息,1表示第一根K线,2表示最后一个数据,0表示中间位置.
  8973. //例如:BARSTATUS=2表示当天是该数据的最后一个周期.
  8974. this.GetBarStatus=function()
  8975. {
  8976. let result=[];
  8977. if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result
  8978. let lCount=this.Data.Data.length;
  8979. for(var i=0 ;i<lCount;++i)
  8980. {
  8981. if (i==0) result[i]=1;
  8982. else if (i==lCount-1) result[i]=2;
  8983. else result[i]=0;
  8984. }
  8985. return result;
  8986. }
  8987. //融资融券函数
  8988. this.GetMarginCacheData = function (id, node)
  8989. {
  8990. let jobID = JS_EXECUTE_JOB_ID.GetMarginJobID(id);
  8991. if (!jobID) this.Execute.ThrowUnexpectedNode(node, '不支持MARGIN(' + id + ')');
  8992. if (this.MarginData.has(jobID)) return this.MarginData.get(jobID);
  8993. return [];
  8994. }
  8995. //下融资融券
  8996. this.GetMarginData = function (jobID)
  8997. {
  8998. if (this.MarginData.has(jobID)) return this.Execute.RunNextJob();
  8999. JSConsole.Complier.Log('[JSSymbolData::GetMarginData] jobID=', jobID);
  9000. var self = this;
  9001. let fieldList = ["name", "date", "symbol"];
  9002. switch (jobID)
  9003. {
  9004. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BALANCE: //融资融券余额
  9005. fieldList.push("margin.balance");
  9006. break;
  9007. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_RATE: //融资占比
  9008. fieldList.push("margin.rate");
  9009. break;
  9010. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_BALANCE: //买入信息-融资余额
  9011. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_AMOUNT: //买入信息-买入额
  9012. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_REPAY: //买入信息-偿还额
  9013. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_NET: //买入信息-融资净买入
  9014. fieldList.push("margin.buy");
  9015. break;
  9016. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_BALANCE: //卖出信息-融券余量
  9017. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_VOLUME: //卖出信息-卖出量
  9018. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_REPAY: //卖出信息-偿还量
  9019. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_NET: //卖出信息-融券净卖出
  9020. fieldList.push("margin.sell");
  9021. break;
  9022. }
  9023. //请求数据
  9024. JSNetwork.HttpRequest({
  9025. url: this.StockHistoryDayApiUrl,
  9026. data:
  9027. {
  9028. "field": fieldList,
  9029. "symbol": [this.Symbol],
  9030. "orderfield": "date"
  9031. },
  9032. method: 'POST',
  9033. dataType: "json",
  9034. async: true,
  9035. success: function (recvData) {
  9036. self.RecvMarginData(recvData, jobID);
  9037. self.Execute.RunNextJob();
  9038. }
  9039. });
  9040. }
  9041. this.RecvMarginData = function (recvData, jobID)
  9042. {
  9043. var data = recvData.data;
  9044. //JSConsole.Complier.Log(data);
  9045. if (!data.stock || data.stock.length != 1) return;
  9046. let stock = data.stock[0];
  9047. var aryData = new Array();
  9048. var aryData2 = [], aryData3 = [], aryData4 = []; //其他3个数据
  9049. for (let i in stock.stockday)
  9050. {
  9051. var item = stock.stockday[i];
  9052. var marginData = item.margin;
  9053. if (!marginData) continue;
  9054. let indexData = new JSCommonData.SingleData();
  9055. indexData.Date = item.date;
  9056. switch (jobID)
  9057. {
  9058. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BALANCE:
  9059. if (!this.IsNumber(marginData.balance)) continue;
  9060. indexData.Value = marginData.balance; //融资融券余额
  9061. aryData.push(indexData);
  9062. break;
  9063. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_RATE:
  9064. if (!this.IsNumber(marginData.rate)) continue;
  9065. indexData.Value = marginData.rate; //融资占比
  9066. aryData.push(indexData);
  9067. break;
  9068. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_BALANCE: //买入信息-融资余额
  9069. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_AMOUNT: //买入信息-买入额
  9070. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_REPAY: //买入信息-偿还额
  9071. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_NET: //买入信息-融资净买入
  9072. var buyData = marginData.buy;
  9073. if (!buyData) continue;
  9074. if (!this.IsNumber(buyData.balance) || !this.IsNumber(buyData.amount) || !this.IsNumber(buyData.repay) || !this.IsNumber(buyData.net)) continue;
  9075. indexData.Value = buyData.balance;
  9076. var indexData2 = new JSCommonData.SingleData();
  9077. indexData2.Date = item.date;
  9078. indexData2.Value = buyData.amount;
  9079. var indexData3 = new JSCommonData.SingleData();
  9080. indexData3.Date = item.date;
  9081. indexData3.Value = buyData.repay;
  9082. var indexData4 = new JSCommonData.SingleData();
  9083. indexData4.Date = item.date;
  9084. indexData4.Value = buyData.net;
  9085. aryData.push(indexData);
  9086. aryData2.push(indexData2);
  9087. aryData3.push(indexData3);
  9088. aryData4.push(indexData4);
  9089. break;
  9090. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_BALANCE: //卖出信息-融券余量
  9091. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_VOLUME: //卖出信息-卖出量
  9092. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_REPAY: //卖出信息-偿还量
  9093. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_NET: //卖出信息-融券净卖出
  9094. var sellData = marginData.sell;
  9095. if (!sellData) continue;
  9096. if (!this.IsNumber(sellData.balance) || !this.IsNumber(sellData.volume) || !this.IsNumber(sellData.repay) || !this.IsNumber(sellData.net)) continue;
  9097. indexData.Value = buyData.balance;
  9098. var indexData2 = new JSCommonData.SingleData();
  9099. indexData2.Date = item.date;
  9100. indexData2.Value = buyData.volume;
  9101. var indexData3 = new JSCommonData.SingleData();
  9102. indexData3.Date = item.date;
  9103. indexData3.Value = buyData.repay;
  9104. var indexData4 = new JSCommonData.SingleData();
  9105. indexData4.Date = item.date;
  9106. indexData4.Value = buyData.net;
  9107. aryData.push(indexData);
  9108. aryData2.push(indexData2);
  9109. aryData3.push(indexData3);
  9110. aryData4.push(indexData4);
  9111. break;
  9112. default:
  9113. continue;
  9114. }
  9115. }
  9116. var allData = [];
  9117. if (jobID === JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BALANCE || jobID === JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_RATE)
  9118. {
  9119. allData.push({ JobID: jobID, Data: aryData });
  9120. }
  9121. else if (jobID === JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_BALANCE || jobID === JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_AMOUNT ||
  9122. jobID === JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_REPAY || jobID === JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_NET)
  9123. {
  9124. allData.push({ JobID: JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_BALANCE, Data: aryData });
  9125. allData.push({ JobID: JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_AMOUNT, Data: aryData2 });
  9126. allData.push({ JobID: JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_REPAY, Data: aryData3 });
  9127. allData.push({ JobID: JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_NET, Data: aryData4 });
  9128. }
  9129. else if (jobID === JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_BALANCE || jobID === JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_VOLUME ||
  9130. jobID === JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_REPAY || jobID === JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_NET)
  9131. {
  9132. allData.push({ JobID: JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_BALANCE, Data: aryData });
  9133. allData.push({ JobID: JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_VOLUME, Data: aryData2 });
  9134. allData.push({ JobID: JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_REPAY, Data: aryData3 });
  9135. allData.push({ JobID: JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_NET, Data: aryData4 });
  9136. }
  9137. for (let i in allData)
  9138. {
  9139. let aryFixedData = this.Data.GetFittingData(allData[i].Data);
  9140. var bindData = new JSCommonData.ChartData();
  9141. bindData.Data = aryFixedData;
  9142. bindData.Period = this.Period; //周期
  9143. if (bindData.Period > 0) //周期数据
  9144. {
  9145. var periodData = bindData.GetPeriodSingleData(bindData.Period);
  9146. bindData.Data = periodData;
  9147. }
  9148. let data = bindData.GetValue();
  9149. this.MarginData.set(allData[i].JobID, data);
  9150. }
  9151. }
  9152. this.GetNewsAnalysisCacheData = function (id, node)
  9153. {
  9154. let jobID = JS_EXECUTE_JOB_ID.GetNewsAnalysisID(id);
  9155. if (!jobID) this.Execute.ThrowUnexpectedNode(node, '不支持NEWS(' + id + ')');
  9156. if (this.NewsAnalysisData.has(jobID)) return this.NewsAnalysisData.get(jobID);
  9157. return [];
  9158. }
  9159. //下载新闻统计
  9160. this.GetNewsAnalysisData = function (jobID)
  9161. {
  9162. if (this.NewsAnalysisData.has(jobID)) return this.Execute.RunNextJob();
  9163. var self = this;
  9164. var mapFolder = new Map([
  9165. [JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_NEGATIVE, "negative"],
  9166. [JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_RESEARCH, 'research'],
  9167. [JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_INTERACT, 'interact'],
  9168. [JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE, 'holderchange'], //NEWS(4) 股东增持
  9169. [JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE2, 'holderchange'], //NEWS(5) 股东减持
  9170. [JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_TRUSTHOLDER, 'trustholder'], //NEWS(6) 信托持股
  9171. [JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_BLOCKTRADING, 'Blocktrading'], //NEWS(7) 大宗交易
  9172. [JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_COMPANYNEWS, 'companynews'], //NEWS(8) 官网新闻
  9173. [JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_TOPMANAGERS, 'topmanagers'], //NEWS(9) 高管要闻
  9174. [JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_PLEDGE, 'Pledge'], //NEWS(10) 股权质押
  9175. ]);
  9176. if (!mapFolder.has(jobID))
  9177. {
  9178. this.Execute.RunNextJob();
  9179. return;
  9180. }
  9181. var folderName = mapFolder.get(jobID);
  9182. var url = this.StockNewsAnalysisApiUrl + '/' + folderName + '/' + this.Symbol + '.json';
  9183. //请求数据
  9184. JSNetwork.HttpRequest({
  9185. url: url,
  9186. method: 'GET',
  9187. dataType: "json",
  9188. async: true,
  9189. success: function (recvData)
  9190. {
  9191. if (recvData.statusCode==200)
  9192. self.RecvNewsAnalysisData(recvData, jobID);
  9193. else
  9194. self.RecvNewsAnalysisDataError(recvData, jobID);
  9195. self.Execute.RunNextJob();
  9196. },
  9197. fail: function (request, textStatus)
  9198. {
  9199. //self.RecvNewsAnalysisDataError(request, textStatus, jobID);
  9200. self.Execute.RunNextJob();
  9201. }
  9202. });
  9203. }
  9204. this.RecvNewsAnalysisDataError = function (recvData, jobID)
  9205. {
  9206. JSConsole.Complier.Log('[JSSymbolData::RecvNewsAnalysisDataError] request error.', recvData.statusCode);
  9207. //没有新闻使用0数据填充
  9208. var aryData = [];
  9209. for (var i = 0; i < this.Data.Data.length; ++i)
  9210. {
  9211. var item = new JSCommonData.SingleData();
  9212. item.Date = this.Data.Data[i].Date;
  9213. item.Value = 0
  9214. aryData.push(item);
  9215. }
  9216. var bindData = new JSCommonData.ChartData();
  9217. bindData.Data = aryData;
  9218. this.NewsAnalysisData.set(jobID, bindData.GetValue());
  9219. }
  9220. this.RecvNewsAnalysisData = function (recvData, jobID)
  9221. {
  9222. var data=recvData.data;
  9223. if (!data.data || !data.date) return;
  9224. if (data.data.length <= 0 || data.data.length != data.date.length) return;
  9225. JSConsole.Complier.Log('[JSSymbolData::RecvNewsAnalysisData] jobID', jobID, data.update);
  9226. if (jobID == JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE || jobID == JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE2)
  9227. {
  9228. var aryData = [], aryData2 = [];
  9229. for (var i = 0; i < data.data.length; ++i)
  9230. {
  9231. var item = new JSCommonData.SingleData();
  9232. item.Date = data.date[i];
  9233. item.Value = data.data[i];
  9234. if (this.IsNumber(item.Value)) aryData.push(item);
  9235. if (i < data.data2.length)
  9236. {
  9237. item = new JSCommonData.SingleData();
  9238. item.Date = data.date[i];
  9239. item.Value = data.data2[i];
  9240. if (this.IsNumber(item.Value)) aryData2.push(item);
  9241. }
  9242. }
  9243. let aryFixedData = this.Data.GetFittingData2(aryData, 0);
  9244. var bindData = new JSCommonData.ChartData();
  9245. bindData.Data = aryFixedData;
  9246. this.NewsAnalysisData.set(JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE, bindData.GetValue());
  9247. aryFixedData = this.Data.GetFittingData2(aryData2, 0);
  9248. bindData = new JSCommonData.ChartData();
  9249. bindData.Data = aryFixedData;
  9250. this.NewsAnalysisData.set(JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE2, bindData.GetValue());
  9251. }
  9252. else
  9253. {
  9254. var aryData = [];
  9255. for (var i = 0; i < data.data.length; ++i)
  9256. {
  9257. var item = new JSCommonData.SingleData();
  9258. item.Date = data.date[i];
  9259. item.Value = data.data[i];
  9260. aryData.push(item);
  9261. }
  9262. let aryFixedData = this.Data.GetFittingData2(aryData, 0);
  9263. var bindData = new JSCommonData.ChartData();
  9264. bindData.Data = aryFixedData;
  9265. this.NewsAnalysisData.set(jobID, bindData.GetValue());
  9266. }
  9267. }
  9268. this.GetStockDataKey=function(jobItem, aryArgs)
  9269. {
  9270. var key=jobItem.FunctionName;
  9271. if (aryArgs.length>0)
  9272. {
  9273. key+="(";
  9274. for(var i=0;i<aryArgs.length;++i)
  9275. {
  9276. if (i>0) key+=",";
  9277. key+=aryArgs[i].toString();
  9278. }
  9279. key+=")";
  9280. }
  9281. return key;
  9282. }
  9283. this.GetFinance=function(jobItem)
  9284. {
  9285. var aryArgs=this.JobArgumentsToArray(jobItem, 1);
  9286. var lID=aryArgs[0];
  9287. var key=this.GetStockDataKey(jobItem,aryArgs);
  9288. if (this.StockData.has(key)) return this.Execute.RunNextJob();
  9289. var self=this;
  9290. if (this.NetworkFilter)
  9291. {
  9292. var dateRange=this.Data.GetDateRange();
  9293. var obj=
  9294. {
  9295. Name:'JSSymbolData::GetFinance', //类名::
  9296. Explain:'财务数据FINANCE(ID)',
  9297. JobID:jobItem.ID,
  9298. Request:{ Url:self.RealtimeApiUrl, Type:'POST', Data:{ id:lID, symbol: this.Symbol, daterange:dateRange } },
  9299. Self:this,
  9300. PreventDefault:false
  9301. };
  9302. this.NetworkFilter(obj, function(recvData)
  9303. {
  9304. self.RecvStockValue(recvData,jobItem,key,0);
  9305. self.Execute.RunNextJob();
  9306. });
  9307. if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求
  9308. }
  9309. var apiDownload=new DownloadFinanceData(
  9310. {
  9311. Job:jobItem,
  9312. Symbol:this.Symbol,
  9313. Url:this.StockHistoryDayApiUrl,
  9314. RealtimeUrl:this.RealtimeApiUrl,
  9315. Args:aryArgs,
  9316. DataKey:key,
  9317. Callback:function(recvData, jobItem, key)
  9318. {
  9319. self.RecvStockValue(recvData, jobItem, key,0);
  9320. self.Execute.RunNextJob();
  9321. },
  9322. ErrorCallback:function(strError)
  9323. {
  9324. self.AddStockValueError(key,strError);
  9325. }
  9326. });
  9327. apiDownload.Download();
  9328. }
  9329. this.GetVariantData=function(jobItem)
  9330. {
  9331. var key=jobItem.VariantName;
  9332. if (this.StockData.has(key)) return this.Execute.RunNextJob();
  9333. var self=this;
  9334. if (this.NetworkFilter)
  9335. {
  9336. var dateRange=this.Data.GetDateRange();
  9337. var obj=
  9338. {
  9339. Name:'JSSymbolData::GetVariantData', //类名::
  9340. Explain:'变量数据下载',
  9341. JobID:jobItem.ID,
  9342. Request:{ Url:"数据地址", Type:'POST', Data:{ VariantName:jobItem.VariantName, symbol: this.Symbol, daterange:dateRange } },
  9343. Self:this,
  9344. PreventDefault:false
  9345. };
  9346. this.NetworkFilter(obj, function(recvData)
  9347. {
  9348. if (recvData.Error)
  9349. {
  9350. self.AddStockValueError(key,recvData.Error);
  9351. }
  9352. else
  9353. {
  9354. var dataType=0;
  9355. if (IFrameSplitOperator.IsNumber(recvData.DataType)) dataType=recvData.DataType;
  9356. self.RecvStockValue(recvData.Data,jobItem,key,dataType);
  9357. }
  9358. self.Execute.RunNextJob();
  9359. });
  9360. if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求
  9361. }
  9362. var errorCallback=function(strError)
  9363. {
  9364. self.AddStockValueError(key,strError);
  9365. };
  9366. var apiDownload;
  9367. if (jobItem.VariantName=="CAPITAL" || jobItem.VariantName=="TOTALCAPITAL" || jobItem.VariantName=="EXCHANGE")
  9368. {
  9369. var callback=function(recvData, jobItem, key)
  9370. {
  9371. self.RecvStockValue(recvData, jobItem, key,0);
  9372. self.Execute.RunNextJob();
  9373. };
  9374. apiDownload=new DownloadFinanceData(
  9375. {
  9376. Job:jobItem,
  9377. Symbol:this.Symbol,
  9378. Url:this.StockHistoryDayApiUrl,
  9379. RealtimeUrl:this.RealtimeApiUrl,
  9380. Args:[jobItem.VariantName],
  9381. DataKey:key,
  9382. Callback:callback,
  9383. ErrorCallback:errorCallback
  9384. });
  9385. }
  9386. else if (jobItem.VariantName=="HYBLOCK" || jobItem.VariantName=="DYBLOCK" || jobItem.VariantName=="GNBLOCK")
  9387. {
  9388. var callback=function(recvData, jobItem, key, dataType)
  9389. {
  9390. self.RecvStockValue(recvData, jobItem, key, dataType);
  9391. self.Execute.RunNextJob();
  9392. };
  9393. apiDownload=new DownloadGroupData(
  9394. {
  9395. Job:jobItem,
  9396. Symbol:this.Symbol,
  9397. Url:this.StockHistoryDayApiUrl,
  9398. RealtimeUrl:this.RealtimeApiUrl,
  9399. Args:[jobItem.VariantName],
  9400. DataKey:key,
  9401. Callback:callback,
  9402. ErrorCallback:errorCallback
  9403. });
  9404. }
  9405. else if (jobItem.VariantName=="INBLOCK")
  9406. {
  9407. var errorMessage=`${jobItem.VariantName}, 请对接外部数据.`;
  9408. this.AddStockValueError(key,errorMessage);
  9409. this.Execute.RunNextJob();
  9410. return;
  9411. }
  9412. else
  9413. {
  9414. var errorMessage=`不支持变量${jobItem.VariantName}, 请对接外部数据.`;
  9415. this.AddStockValueError(key,errorMessage);
  9416. this.Execute.RunNextJob();
  9417. return;
  9418. }
  9419. apiDownload.Download();
  9420. }
  9421. this.GetProFinance=function(jobItem)
  9422. {
  9423. var jobID=jobItem.ID;
  9424. var finder=null;
  9425. for(var i=0;i<JS_ARRAY_PROFESSIONAL_FINANCE.length;++i)
  9426. {
  9427. var item=JS_ARRAY_PROFESSIONAL_FINANCE[i];
  9428. if (item.JobID==jobID)
  9429. {
  9430. finder=item;
  9431. break;
  9432. }
  9433. }
  9434. if (!finder) return this.Execute.RunNextJob();
  9435. var aryArgs=this.JobArgumentsToArray(jobItem, finder.ArgCount);
  9436. var key=this.GetStockDataKey(jobItem,aryArgs);
  9437. if (this.StockData.has(key)) return this.Execute.RunNextJob();
  9438. var self=this;
  9439. var dataType=0;
  9440. if ([JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_GPJYVALUE,JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SCJYVALUE,JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_BKJYVALUE].includes(jobID))
  9441. {
  9442. dataType=aryArgs[2]==1?0:2; //TYPE:为1表示做平滑处理,没有数据的周期返回上一周期的值;为0表示不做平滑处理
  9443. }
  9444. if (this.NetworkFilter)
  9445. {
  9446. var dateRange=this.Data.GetDateRange();
  9447. var obj=
  9448. {
  9449. Name:finder.FuncName, //类名::
  9450. Explain:finder.Explain,
  9451. JobID:jobID,
  9452. Request:{ Url:self.StockHistoryDayApiUrl, Type:'POST', Data:{ Args:aryArgs, symbol: this.Symbol, daterange:dateRange } },
  9453. Self:this,
  9454. PreventDefault:false
  9455. };
  9456. this.NetworkFilter(obj, function(recvData)
  9457. {
  9458. self.RecvStockValue(recvData,jobItem,key,dataType);
  9459. self.Execute.RunNextJob();
  9460. });
  9461. if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求
  9462. }
  9463. JSConsole.Chart.Warn(`[JSSymbolData::GetProFinance] ${finder.FuncName} Not implemented.`);
  9464. }
  9465. //自定义变量数据下载
  9466. this.GetCustomVariantData=function(jobItem)
  9467. {
  9468. var key=jobItem.VariantName;
  9469. if (this.StockData.has(key)) return this.Execute.RunNextJob();
  9470. var variantInfo=g_JSComplierResource.CustomVariant.Data.get(key);
  9471. var self=this;
  9472. if (this.NetworkFilter)
  9473. {
  9474. var dateRange=this.Data.GetDateRange();
  9475. var obj=
  9476. {
  9477. Name:'JSSymbolData::GetCustomVariantData', //类名::函数名
  9478. Explain:'自定义变量数据下载',
  9479. JobID:jobItem.ID,
  9480. Request:{ Url:"数据地址", Type:'POST', Data:{ VariantName:jobItem.VariantName, symbol: this.Symbol, daterange:dateRange } },
  9481. Self:this,
  9482. VariantInfo:variantInfo,
  9483. PreventDefault:false
  9484. };
  9485. this.NetworkFilter(obj, function(recvData)
  9486. {
  9487. if (recvData.Error) self.AddStockValueError(key,recvData.Error);
  9488. else self.RecvStockValue(recvData.Data,jobItem,key,recvData.DataType);
  9489. self.Execute.RunNextJob();
  9490. });
  9491. }
  9492. else
  9493. {
  9494. this.AddStockValueError(key, `自定义变量${key}下载失败`);
  9495. this.Execute.RunNextJob();
  9496. }
  9497. }
  9498. this.GetCustomFunctionData=function(jobItem)
  9499. {
  9500. var key=jobItem.FunctionName;
  9501. var functionInfo=g_JSComplierResource.CustomFunction.Data.get(key);
  9502. if (!functionInfo.IsDownload) return this.Execute.RunNextJob();
  9503. if (this.StockData.has(key)) return this.Execute.RunNextJob(); //一个函数只能缓存一个数据, 保存多个外部自己保存
  9504. var self=this;
  9505. if (this.NetworkFilter)
  9506. {
  9507. var dateRange=this.Data.GetDateRange();
  9508. var obj=
  9509. {
  9510. Name:'JSSymbolData::GetCustomFunctionData', //类名::函数名
  9511. Explain:'自定义函数数据下载',
  9512. JobID:jobItem.ID,
  9513. Request:
  9514. {
  9515. Url:"数据地址", Type:'POST',
  9516. Data:
  9517. {
  9518. FunctionName:jobItem.FunctionName,
  9519. symbol: this.Symbol, daterange:dateRange,
  9520. JobItem:jobItem //函数编译信息
  9521. }
  9522. },
  9523. Self:this,
  9524. FunctionInfo:functionInfo,
  9525. PreventDefault:false
  9526. };
  9527. this.NetworkFilter(obj, function(recvData)
  9528. {
  9529. if (recvData.Error) self.AddStockValueError(key,recvData.Error);
  9530. else self.RecvStockValue(recvData.Data,jobItem,key,recvData.DataType);
  9531. self.Execute.RunNextJob();
  9532. });
  9533. }
  9534. else
  9535. {
  9536. this.AddStockValueError(key, `自定义函数${key}下载失败`);
  9537. this.Execute.RunNextJob();
  9538. }
  9539. }
  9540. this.GetCustomFunctionDataV2=function(jobItem)
  9541. {
  9542. var funcName=jobItem.FunctionName;
  9543. var functionInfo=g_JSComplierResource.CustomDataFunction.Data.get(funcName);
  9544. if (!functionInfo) return;
  9545. var aryArgs=this.JobArgumentsToArray(jobItem, functionInfo.ArgCount);
  9546. var key=this.GetStockDataKey(jobItem,aryArgs);
  9547. if (this.StockData.has(key)) return this.Execute.RunNextJob(); //一个函数只能缓存一个数据, 保存多个外部自己保存
  9548. var self=this;
  9549. if (this.NetworkFilter)
  9550. {
  9551. var dateRange=this.Data.GetDateRange();
  9552. var obj=
  9553. {
  9554. Name:'JSSymbolData::GetCustomFunctionData', //类名::函数名
  9555. Explain:'自定义函数数据下载',
  9556. JobID:jobItem.ID,
  9557. Request:
  9558. {
  9559. Url:"数据地址", Type:'POST',
  9560. Data:
  9561. {
  9562. FunctionName:jobItem.FunctionName,
  9563. symbol: this.Symbol, daterange:dateRange,
  9564. JobItem:jobItem, //函数编译信息
  9565. Key:key,
  9566. period:this.Period,
  9567. right:this.Right,
  9568. }
  9569. },
  9570. Self:this,
  9571. FunctionInfo:functionInfo,
  9572. PreventDefault:false
  9573. };
  9574. this.NetworkFilter(obj, function(recvData)
  9575. {
  9576. if (recvData.Error) self.AddStockValueError(key,recvData.Error);
  9577. else self.RecvStockValue(recvData.Data,jobItem,key,recvData.DataType);
  9578. self.Execute.RunNextJob();
  9579. });
  9580. }
  9581. else
  9582. {
  9583. this.AddStockValueError(key, `自定义函数${key}下载失败`);
  9584. this.Execute.RunNextJob();
  9585. }
  9586. }
  9587. this.RecvStockValue=function(recvData,jobItem,key,dataType)
  9588. {
  9589. if (!recvData)
  9590. {
  9591. JSConsole.Complier.Log(`[JSSymbolData::RecvStockValue] key=${key} data is null`);
  9592. return;
  9593. }
  9594. if (dataType==0)
  9595. {
  9596. if (Array.isArray(recvData))
  9597. {
  9598. var kdata=this.Data; //K线
  9599. var aryFittingData;
  9600. if (this.DataType==HQ_DATA_TYPE.KLINE_ID)
  9601. {
  9602. if (JSCommonData.ChartData.IsDayPeriod(this.Period,true))
  9603. aryFittingData=kdata.GetFittingFinanceData(recvData); //数据和主图K线拟合
  9604. else if (JSCommonData.ChartData.IsMinutePeriod(this.Period,true))
  9605. aryFittingData=kdata.GetMinuteFittingFinanceData(recvData); //数据和主图K线拟合
  9606. else
  9607. return;
  9608. }
  9609. else
  9610. {
  9611. aryFittingData=kdata.GetMinuteFittingFinanceData(recvData); //数据和主图分时拟合
  9612. }
  9613. var bindData=new JSCommonData.ChartData();
  9614. bindData.Data=aryFittingData;
  9615. var result=bindData.GetValue();
  9616. if (key=="EXCHANGE") //计算换手率=成交量/流通股本*100
  9617. {
  9618. for(var i in result)
  9619. {
  9620. var kitem=kdata.Data[i];
  9621. if (result[i]>0)
  9622. result[i]=kitem.Vol/result[i] * 100;
  9623. }
  9624. }
  9625. this.StockData.set(key,{ Data:result });
  9626. }
  9627. else
  9628. {
  9629. this.StockData.set(key,{ Data:recvData.Value });
  9630. }
  9631. }
  9632. else if (dataType==1) //单数值
  9633. {
  9634. this.StockData.set(key,{ Data:recvData.Value });
  9635. }
  9636. else if (dataType==2) //数据不做平滑处理
  9637. {
  9638. var kdata=this.Data; //K线
  9639. var aryFittingData;
  9640. if (this.DataType==HQ_DATA_TYPE.KLINE_ID)
  9641. {
  9642. if (JSCommonData.ChartData.IsDayPeriod(this.Period,true))
  9643. aryFittingData=kdata.GetFittingTradeData(recvData, 0, false); //数据和主图K线拟合
  9644. else if (JSCommonData.ChartData.IsMinutePeriod(this.Period,true))
  9645. aryFittingData=kdata.GetMinuteFittingTradeData(recvData, 0, false); //数据和主图K线拟合
  9646. else
  9647. return;
  9648. }
  9649. else
  9650. {
  9651. aryFittingData=kdata.GetMinuteFittingTradeData(recvData, 0); //数据和主图分钟拟合
  9652. }
  9653. var bindData=new JSCommonData.ChartData();
  9654. bindData.Data=aryFittingData;
  9655. var result=bindData.GetValue();
  9656. this.StockData.set(key,{ Data:result });
  9657. }
  9658. }
  9659. this.AddStockValueError=function(key, message)
  9660. {
  9661. this.StockData.set(key,{ Error:message });
  9662. }
  9663. this.GetStockCacheData=function(obj)
  9664. {
  9665. var key;
  9666. if (obj.FunctionName)
  9667. key=this.GetStockDataKey({FunctionName:obj.FunctionName}, obj.Args);
  9668. else if (obj.VariantName)
  9669. key=obj.VariantName;
  9670. else if (obj.CustomName)
  9671. key=obj.CustomName; //自定义名字
  9672. else
  9673. return null;
  9674. if (!this.StockData.has(key)) return null;
  9675. var data=this.StockData.get(key);
  9676. if (data.Error) this.Execute.ThrowUnexpectedNode(obj.Node, data.Error);
  9677. return data.Data;
  9678. }
  9679. this.IsInBlock=function(blockName, node)
  9680. {
  9681. var data=this.GetStockCacheData({ VariantName:"INBLOCK", Node:node });
  9682. if (!data) return 0;
  9683. var aryBlock=data.split('|');
  9684. for(var i=0; i<aryBlock.length; ++i)
  9685. {
  9686. var item=aryBlock[i];
  9687. if (item==blockName) return 1;
  9688. }
  9689. return 0;
  9690. }
  9691. /*
  9692. 飞狐函数 SYSPARAM
  9693. SYSPARAM(1)画面上光标位置(K线序号)
  9694. SYSPARAM(2)主图可见K线最初位置
  9695. SYSPARAM(3)主图可见K线最后位置注意该函数仅K线图形分析且打开十字光标时有效,否则返回值不确定
  9696. SYSPARAM(4)主图可见K线最高价注意该函数仅K线图形分析且打开十字光标时有效,否则返回值不确定
  9697. SYSPARAM(5)主图可见K线最低价注意该函数仅K线图形分析且打开十字光标时有效,否则返回值不确定
  9698. SYSPARAM(6)画面上光标数值注意该函数仅K线图形分析且打开十字光标时有效,否则返回值不确定
  9699. */
  9700. this.SysParam=function(id, jsExec)
  9701. {
  9702. if (!this.DrawInfo) return [];
  9703. if (id==2)
  9704. {
  9705. jsExec.IsUsePageData=true;
  9706. if (IFrameSplitOperator.IsNumber(this.DrawInfo.Start))
  9707. return this.DrawInfo.Start+1;
  9708. }
  9709. else if (id==3)
  9710. {
  9711. jsExec.IsUsePageData=true;
  9712. if (IFrameSplitOperator.IsNumber(this.DrawInfo.End))
  9713. return this.DrawInfo.End+1;
  9714. }
  9715. else if (id==4)
  9716. {
  9717. jsExec.IsUsePageData=true;
  9718. if (!IFrameSplitOperator.IsNumber(this.DrawInfo.End) ||!IFrameSplitOperator.IsNumber(this.DrawInfo.Start)) return [];
  9719. if (!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return [];
  9720. var high=null;
  9721. for(var i=this.DrawInfo.Start; i<=this.DrawInfo.End && i<this.Data.Data.length; ++i)
  9722. {
  9723. var item=this.Data.Data[i];
  9724. if (!IFrameSplitOperator.IsNumber(item.High)) continue;
  9725. if (high==null) high=item.High;
  9726. else if(high<item.High) high=item.High;
  9727. }
  9728. return high;
  9729. }
  9730. else if (id==5)
  9731. {
  9732. jsExec.IsUsePageData=true;
  9733. if (!IFrameSplitOperator.IsNumber(this.DrawInfo.End) ||!IFrameSplitOperator.IsNumber(this.DrawInfo.Start)) return [];
  9734. if (!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return [];
  9735. var low=null;
  9736. for(var i=this.DrawInfo.Start;i<=this.DrawInfo.End && i<this.Data.Data.length;++i)
  9737. {
  9738. var item=this.Data.Data[i];
  9739. if (!IFrameSplitOperator.IsNumber(item.Low)) continue;
  9740. if (low==null) low=item.Low;
  9741. else if(low>item.Low) low=item.Low;
  9742. }
  9743. return low;
  9744. }
  9745. return [];
  9746. }
  9747. this.JobArgumentsToArray=function(job, lCount)
  9748. {
  9749. var args=job.Args;
  9750. if (args.length!=lCount)
  9751. {
  9752. var token=job.Token;
  9753. this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`${job.FunctionName}() Error: argument count error.`);
  9754. }
  9755. var aryValue=[];
  9756. for(var i=0;i<args.length;++i)
  9757. {
  9758. var item=args[i];
  9759. if (this.IsNumber(item))
  9760. {
  9761. aryValue.push(item);
  9762. }
  9763. else if (item.Type==Syntax.Literal)
  9764. {
  9765. aryValue.push(item.Value);
  9766. }
  9767. else if (item.Type==Syntax.Identifier) //变量 !!只支持默认的变量值
  9768. {
  9769. var isFind=false;
  9770. for(var j in this.Arguments)
  9771. {
  9772. const argItem=this.Arguments[j];
  9773. if (argItem.Name==item.Name)
  9774. {
  9775. aryValue.push(argItem.Value);
  9776. isFind=true;
  9777. break;
  9778. }
  9779. }
  9780. if (!isFind)
  9781. {
  9782. var token=job.Token;
  9783. this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`${job.FunctionName}() Error: can't read ${item.Name}`);
  9784. }
  9785. }
  9786. }
  9787. return aryValue;
  9788. }
  9789. this.DownloadCustomAPIData = function (job)
  9790. {
  9791. if (!this.NetworkFilter) return this.Execute.RunNextJob();
  9792. var args = [];
  9793. for (var i in job.Args)
  9794. {
  9795. var item = job.Args[i];
  9796. if (item.Type == Syntax.Literal)
  9797. {
  9798. args.push(item.Value);
  9799. }
  9800. else if (item.Type == Syntax.Identifier) //变量 !!只支持默认的变量值
  9801. {
  9802. var isFind = false;
  9803. for (var j in this.Arguments)
  9804. {
  9805. const argItem = this.Arguments[j];
  9806. if (argItem.Name == item.Name)
  9807. {
  9808. args.push(argItem.Value);
  9809. isFind = true;
  9810. break;
  9811. }
  9812. }
  9813. if (!isFind)
  9814. {
  9815. var token = job.Token;
  9816. this.Execute.ErrorHandler.ThrowError(token.Index, token.Line, 0, `LoadAPIData() Error: can't read ${item.Name}`);
  9817. }
  9818. }
  9819. else
  9820. {
  9821. return this.Execute.RunNextJob();
  9822. }
  9823. }
  9824. var self = this;
  9825. var obj =
  9826. {
  9827. Name: 'JSSymbolData::DownloadCustomAPIData', //类名::函数名
  9828. Explain: '下载自定义api数据',
  9829. Period: this.Period,
  9830. Right: this.Right,
  9831. Symbol: this.Symbol,
  9832. KData: this.Data, //K线数据
  9833. Cache: this.CustomAPIData,
  9834. Args: args,
  9835. Self: this,
  9836. PreventDefault: false
  9837. };
  9838. this.NetworkFilter(obj, function (data) {
  9839. self.RecvCustomAPIData(data, args);
  9840. self.Execute.RunNextJob();
  9841. });
  9842. if (obj.PreventDefault == true) return; //已被上层替换,不调用默认的网络请求
  9843. this.Execute.RunNextJob();
  9844. }
  9845. this.RecvCustomAPIData = function (recvData, args)
  9846. {
  9847. if (!recvData || !recvData.data) return;
  9848. var data = recvData.data;
  9849. var apiKey = this.GenerateCustomAPIKey(args);
  9850. if (JSCommonData.ChartData.IsMinutePeriod(this.Period, true))
  9851. {
  9852. if (!data.date || !data.time) return;
  9853. var date = data.date;
  9854. var time = data.time;
  9855. for (var key in data)
  9856. {
  9857. if (key == 'date' || key == 'time') continue;
  9858. var item = data[key];
  9859. }
  9860. }
  9861. else if (JSCommonData.ChartData.IsDayPeriod(this.Period, true))
  9862. {
  9863. if (!data.date) return;
  9864. var date = data.date;
  9865. var result = { __Type__: "Object" };
  9866. for (var key in data) {
  9867. if (key == 'date') continue;
  9868. var item = data[key];
  9869. if (Array.isArray(item))
  9870. {
  9871. var value = this.FittingCustomAPIArray(item, date);
  9872. result[key] = value;
  9873. }
  9874. else if (this.IsNumber(item))
  9875. {
  9876. result[key] = item;
  9877. }
  9878. }
  9879. this.CustomAPIData.set(apiKey, result);
  9880. }
  9881. }
  9882. this.FittingCustomAPIArray = function (data, date, time)
  9883. {
  9884. var kdata = this.Data; //K线
  9885. var arySingleData = [];
  9886. for (var i in data)
  9887. {
  9888. var value = data[i];
  9889. var indexItem = new JSCommonData.SingleData(); //单列指标数据
  9890. indexItem.Date = date[i];
  9891. if (time && i < time.length) indexItem.Time = time[i];
  9892. indexItem.Value = value;
  9893. arySingleData.push(indexItem);
  9894. }
  9895. var aryFittingData;
  9896. if (JSCommonData.ChartData.IsDayPeriod(this.Period, true))
  9897. aryFittingData = kdata.GetFittingData(arySingleData); //数据和主图K线拟合
  9898. else if (JSCommonData.ChartData.IsMinutePeriod(this.Period, true))
  9899. aryFittingData = kdata.GetMinuteFittingData(arySingleData); //数据和主图K线拟合
  9900. else
  9901. return null;
  9902. var bindData = new JSCommonData.ChartData();
  9903. bindData.Data = aryFittingData;
  9904. var result = bindData.GetValue();
  9905. return result;
  9906. }
  9907. //MA.MA1#WEEK
  9908. this.ReadIndexFunctionValue=function(item, result) //返回 {Period:周期, Out:输出变量, Error:, Name:脚本名字 }
  9909. {
  9910. var indexParam={};
  9911. if (typeof(item)=== 'object')
  9912. {
  9913. if (!this.ReadArgumentValue(item,indexParam))
  9914. {
  9915. result.Error=indexParam.Error;
  9916. return false;
  9917. }
  9918. }
  9919. else
  9920. {
  9921. indexParam.Value=item;
  9922. }
  9923. var pos=indexParam.Value.indexOf("\.");
  9924. if (pos!=-1)
  9925. {
  9926. result.Name=indexParam.Value.slice(0, pos); //名字
  9927. var pos2=indexParam.Value.indexOf('#', pos+1);
  9928. if (pos2!=-1)
  9929. {
  9930. result.Out=indexParam.Value.slice(pos+1, pos2); //输出变量
  9931. result.Period=indexParam.Value.slice(pos2+1); //周期
  9932. }
  9933. else
  9934. {
  9935. result.Out=indexParam.Value.slice(pos+1);
  9936. }
  9937. }
  9938. else
  9939. {
  9940. var pos2=indexParam.Value.indexOf('#');
  9941. if (pos2!=-1)
  9942. {
  9943. result.Name=indexParam.Value.slice(0,pos2);
  9944. result.Period=indexParam.Value.slice(pos2+1); //周期
  9945. }
  9946. else
  9947. {
  9948. result.Name=indexParam.Value;
  9949. }
  9950. }
  9951. const PERIOD_MAP=new Map([
  9952. ["DAY",0 ], ["WEEK", 1 ], ["MONTH",2 ], ["SEASON",9 ], ["YEAR", 3], ["HALFYEAR",22], ["WEEK2",21],
  9953. ["MIN1", 4], ["MIN5", 5 ], ["MIN15", 6 ], ["MIN30",7 ], ["MIN60", 8 ],["MIN120",11],["MIN240",12],
  9954. ["DAY2", 40002],["MULTIDAY",40002],["DAY3", 40003],["DAY4", 40004],["DAY5",40005],
  9955. ["DAY6", 40006],["DAY7", 40007],["DAY8", 40008],["DAY9", 40009],["DAY10",40010],
  9956. ["DAY11", 40011],["DAY12", 40012],["DAY13", 40013],["DAY14", 40014],["DAY15", 40015],
  9957. ]);
  9958. if (result.Period)
  9959. {
  9960. if (!PERIOD_MAP.has(result.Period))
  9961. {
  9962. result.Error=`${result.Period}, 周期错误`;
  9963. return false;
  9964. }
  9965. result.PeriodID=PERIOD_MAP.get(result.Period);
  9966. }
  9967. return true;
  9968. }
  9969. this.ReadSymbolArgumentValue=function(item, result) //返回{ Value:股票代码, Error:错误信息}
  9970. {
  9971. var readArgument={};
  9972. if (typeof(item)=== 'object')
  9973. {
  9974. if (!this.ReadArgumentValue(item,readArgument))
  9975. {
  9976. result.Error=readArgument.Error;
  9977. return false;
  9978. }
  9979. }
  9980. else
  9981. {
  9982. readArgument.Value=item;
  9983. }
  9984. if (readArgument.Value=='') readArgument.Value=this.Symbol; //缺省使用股票代码
  9985. var symbol=readArgument.Value;
  9986. //支持 SH60000, SZ000001
  9987. //A股后缀小写
  9988. if (symbol.indexOf('.SH')>0) result.Symbol=symbol.replace('.SH', ".sh");
  9989. else if (symbol.indexOf('.SZ')>0) result.Symbol=symbol.replace('.SZ', ".sz");
  9990. else if (symbol.indexOf("SH")==0) result.Symbol=symbol.slice(2)+".sh";
  9991. else if (symbol.indexOf("SZ")==0) result.Symbol=symbol.slice(2)+".sz";
  9992. else result.Symbol=symbol;
  9993. return true;
  9994. }
  9995. this.ReadIndexArgumentValue=function(args, result)
  9996. {
  9997. result.Args=[];
  9998. for(var i in result.SytemIndex.Args) //复制参数
  9999. {
  10000. var item=result.SytemIndex.Args[i];
  10001. result.Args.push({Value:item.Value, Name:item.Name});
  10002. }
  10003. if (args.length>2 && result.SytemIndex.Args && result.SytemIndex.Args.length>0)
  10004. {
  10005. for(var i=2, j=0; i<args.length && j<result.SytemIndex.Args.length; ++i, ++j)
  10006. {
  10007. var readArgument={};
  10008. var item=args[i];
  10009. if (typeof(item)=== 'object')
  10010. {
  10011. if (!this.ReadArgumentValue(item,readArgument))
  10012. {
  10013. result.Error=readArgument.Error;
  10014. return false;
  10015. }
  10016. }
  10017. else
  10018. {
  10019. readArgument.Value=item;
  10020. }
  10021. result.Args[j].Value=readArgument.Value;
  10022. }
  10023. }
  10024. return true;
  10025. }
  10026. this.ReadArgumentValue=function(item, result) //读取变量值
  10027. {
  10028. result.Name=item.Name;
  10029. if (item.Type==Syntax.Literal)
  10030. {
  10031. result.Value=item.Value;
  10032. return true;
  10033. }
  10034. if (item.Type==Syntax.Identifier)
  10035. {
  10036. var isFind=false;
  10037. for(var i in this.Arguments)
  10038. {
  10039. const argItem=this.Arguments[i];
  10040. if (argItem.Name==item.Name)
  10041. {
  10042. result.Value=argItem.Value;
  10043. isFind=true;
  10044. return true;
  10045. }
  10046. }
  10047. if (!isFind)
  10048. {
  10049. result.Error=`can't read ${item.Name}` ;
  10050. return false;
  10051. }
  10052. }
  10053. result.Error=`can't read ${item.Name}, type error.`;
  10054. return false;
  10055. }
  10056. this.ReadIndexFunctionOut=function(item, result)
  10057. {
  10058. var indexParam={};
  10059. if (typeof(item)=== 'object')
  10060. {
  10061. if (!this.ReadArgumentValue(item,indexParam))
  10062. {
  10063. result.Error=indexParam.Error;
  10064. return false;
  10065. }
  10066. }
  10067. else
  10068. {
  10069. indexParam.Value=item;
  10070. }
  10071. result.OutIndex=indexParam.Value;
  10072. result.Out=null;
  10073. return true;
  10074. }
  10075. //TMP2:=KDJ.K#WEEK;
  10076. this.CallMemberScriptIndex=function(job)
  10077. {
  10078. if (job.Member.Object.Type!=Syntax.Identifier ||job.Member.Property.Type!=Syntax.Identifier)
  10079. {
  10080. var token=job.Token;
  10081. this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallMemberScriptIndex() Error: 参数错误`);
  10082. }
  10083. var objName=job.Member.Object.Name;
  10084. var PropertyName=job.Member.Property.Name;
  10085. if (PropertyName=="" || PropertyName==null)
  10086. {
  10087. var token=job.Token;
  10088. this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallMemberScriptIndex() Error: ${objName}.${PropertyName} 指标输出变量错误`);
  10089. }
  10090. if (this.Execute.VarTable.has(objName))
  10091. {
  10092. var memberValue=this.Execute.VarTable.get(objName);
  10093. if (memberValue.hasOwnProperty(PropertyName))
  10094. {
  10095. JSConsole.Complier.Log(`[JSSymbolData::CallMemberScriptIndex] index data ${objName}.${PropertyName} in cache.`);
  10096. return this.Execute.RunNextJob();
  10097. }
  10098. }
  10099. var callInfo=objName+"."+PropertyName;
  10100. var indexInfo={ Job:job, PeriodID:this.Period , Symbol:this.Symbol };
  10101. if (!this.ReadIndexFunctionValue(callInfo,indexInfo)) //读取指标
  10102. {
  10103. var token=job.Token;
  10104. this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallMemberScriptIndex() Error: '${callInfo}' ${indexInfo.Error}`);
  10105. }
  10106. var systemIndex=new JSIndexScript();
  10107. var systemItem=systemIndex.Get(indexInfo.Name);
  10108. if (!systemItem)
  10109. {
  10110. var token=job.Token;
  10111. this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallMemberScriptIndex() Error: '${callInfo}' ${indexInfo.Name} 指标不存在`);
  10112. }
  10113. if (Array.isArray(systemItem.Args) && systemItem.Args.length>0)
  10114. {
  10115. indexInfo.Args=[];
  10116. for(var i in systemItem.Args) //复制参数
  10117. {
  10118. var item=systemItem.Args[i];
  10119. indexInfo.Args.push({Value:item.Value, Name:item.Name});
  10120. }
  10121. }
  10122. JSConsole.Complier.Log('[JSSymbolData::CallMemberScriptIndex] call script index', indexInfo);
  10123. var dateTimeRange=this.Data.GetDateRange();
  10124. var option=
  10125. {
  10126. HQDataType:this.DataType,
  10127. Symbol:indexInfo.Symbol,
  10128. Name:'',
  10129. Right:this.Right, //复权
  10130. Period:indexInfo.PeriodID, //周期
  10131. Data:null,
  10132. SourceData:null,
  10133. Callback:(outVar,job, symbolData)=> {
  10134. this.RecvMemberScriptIndexData(outVar,job,symbolData);
  10135. this.Execute.RunNextJob();
  10136. },
  10137. CallbackParam:indexInfo,
  10138. Async:true,
  10139. MaxRequestDataCount:this.MaxRequestDataCount+30*2,
  10140. MaxRequestMinuteDayCount:this.MaxRequestMinuteDayCount+2,
  10141. Arguments:indexInfo.Args,
  10142. //Condition:this.Condition,
  10143. IsBeforeData:this.IsBeforeData,
  10144. NetworkFilter:this.NetworkFilter,
  10145. IsApiPeriod:this.IsApiPeriod,
  10146. KLineRange:dateTimeRange //K线数据范围
  10147. };
  10148. //执行脚本
  10149. var run=JSComplier.Execute(systemItem.Script,option,(error, indexInfo)=>{this.ExecuteScriptIndexError(error,indexInfo)});
  10150. }
  10151. this.CallDynamicScriptIndex=function(job, varTable)
  10152. {
  10153. var callInfo=job.DynamicName;
  10154. var indexInfo={ Job:job, PeriodID:this.Period , Symbol:this.Symbol };
  10155. if (!this.ReadIndexFunctionValue(callInfo,indexInfo)) //读取指标
  10156. {
  10157. var token=job.Token;
  10158. this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallDynamicScriptIndex() Error: '${callInfo}' ${indexInfo.Error}`);
  10159. }
  10160. var systemIndex=new JSIndexScript(); //系统指标
  10161. var systemItem=systemIndex.Get(indexInfo.Name);
  10162. if (!systemItem)
  10163. {
  10164. var token=job.Token;
  10165. this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallDynamicScriptIndex() Error: '${callInfo}' ${indexInfo.Name} 指标不存在`);
  10166. }
  10167. indexInfo.SytemIndex=systemItem;
  10168. if (!this.ReadDynamicIndexArgumentValue(job.Args, indexInfo, varTable))
  10169. {
  10170. var token=job.Token;
  10171. this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallDynamicScriptIndex() ${indexInfo.Name} 指标参数错误 : ${indexInfo.Error} `);
  10172. }
  10173. JSConsole.Complier.Log('[JSSymbolData::CallMemberScriptIndex] call script index', indexInfo);
  10174. var dateTimeRange=this.Data.GetDateRange();
  10175. var option=
  10176. {
  10177. HQDataType:this.DataType,
  10178. Symbol:indexInfo.Symbol,
  10179. Name:'',
  10180. Right:this.Right, //复权
  10181. Period:indexInfo.PeriodID, //周期
  10182. Data:null,
  10183. SourceData:null,
  10184. Callback:(outVar,job, symbolData)=> {
  10185. this.RecvDynamicScriptIndexData(outVar,job,symbolData);
  10186. this.Execute.RunNextJob();
  10187. },
  10188. CallbackParam:indexInfo,
  10189. Async:true,
  10190. MaxRequestDataCount:this.MaxRequestDataCount+30*2,
  10191. MaxRequestMinuteDayCount:this.MaxRequestMinuteDayCount+2,
  10192. Arguments:indexInfo.Args,
  10193. //Condition:this.Condition,
  10194. IsBeforeData:this.IsBeforeData,
  10195. NetworkFilter:this.NetworkFilter,
  10196. IsApiPeriod:this.IsApiPeriod,
  10197. KLineRange:dateTimeRange //K线数据范围
  10198. };
  10199. //执行脚本
  10200. var run=JSComplier.Execute(systemItem.Script,option,(error, indexInfo)=>{this.ExecuteScriptIndexError(error,indexInfo)});
  10201. }
  10202. this.ReadDynamicIndexArgumentValue=function(args, result, varTable)
  10203. {
  10204. result.Args=[];
  10205. for(var i =0;i<result.SytemIndex.Args.length; ++i) //复制参数
  10206. {
  10207. var item=result.SytemIndex.Args[i];
  10208. result.Args.push({ Value:item.Value, Name:item.Name, IsDefault:true });
  10209. }
  10210. if (!IFrameSplitOperator.IsNonEmptyArray(args)) return true;
  10211. for(var i=0;i<args.length;++i)
  10212. {
  10213. var item=args[i];
  10214. var argItem=result.Args[i];
  10215. if (!argItem) continue;
  10216. if (item.Type==Syntax.Literal)
  10217. {
  10218. argItem.Value=item.Value;
  10219. argItem.IsDefault=false;
  10220. }
  10221. else if (item.Type==Syntax.Identifier) //支持传参
  10222. {
  10223. if (varTable.has(item.Name))
  10224. {
  10225. argItem.Value=varTable.get(item.Name);
  10226. argItem.IsDefault=false;
  10227. }
  10228. }
  10229. }
  10230. return true;
  10231. }
  10232. /*****************************************************************************************************************************
  10233. 脚本调用
  10234. STKINDI
  10235. STKINDI('600000.sh','MA.MA1#WEEK',5,10,20,30,60,120);
  10236. 1=股票代码 2=指标名字.输出变量#周期, 3....参数
  10237. CALCSTOCKINDEX
  10238. 用法:CALCSTOCKINDEX(品种代码,指标名称,指标线),返回该指标相应输出的计算值.
  10239. 例如:
  10240. CALCSTOCKINDEX('SH600000','KDJ',3)表示上证600000的KDJ指标第3个输出即J之值,第一个参数可在前面加SZ(深市),SH(沪市),BJ(京市),或市场_,,
  10241. CALCSTOCKINDEX('47_IFL0','MACD',2)表示IFL0品种的MACD指标第2个输出值.
  10242. "MA.MA1"(6,12,18)
  10243. *******************************************************************************************************************************/
  10244. this.CallScriptIndex=function(job, varTable)
  10245. {
  10246. if (job.Member) return this.CallMemberScriptIndex(job);
  10247. if (job.DynamicName) return this.CallDynamicScriptIndex(job, varTable);
  10248. if (!job.Args || !(job.Args.length>=2))
  10249. {
  10250. var token=job.Token;
  10251. this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallScriptIndex() Error: ${job.FunctionName} 参数错误`);
  10252. }
  10253. var indexInfo={ Job:job, PeriodID:this.Period };
  10254. if (!this.ReadSymbolArgumentValue(job.Args[0],indexInfo)) //读取代码
  10255. {
  10256. var token=job.Token;
  10257. this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallScriptIndex() Error: ${indexInfo.Error}`);
  10258. }
  10259. if (!this.ReadIndexFunctionValue(job.Args[1],indexInfo)) //读取指标
  10260. {
  10261. var token=job.Token;
  10262. this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallScriptIndex() Error: ${indexInfo.Error}`);
  10263. }
  10264. if (job.FunctionName=="CALCSTOCKINDEX")
  10265. {
  10266. if (!this.ReadIndexFunctionOut(job.Args[2],indexInfo)) //读取返回值索引
  10267. {
  10268. var token=job.Token;
  10269. this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallScriptIndex() Error: ${indexInfo.Error}`);
  10270. }
  10271. }
  10272. var systemIndex=new JSIndexScript();
  10273. var systemItem=systemIndex.Get(indexInfo.Name);
  10274. if (!systemItem)
  10275. {
  10276. var token=job.Token;
  10277. this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallScriptIndex() ${indexInfo.Name} 指标不存在`);
  10278. }
  10279. indexInfo.SytemIndex=systemItem; //系统指标
  10280. if (!this.ReadIndexArgumentValue(job.Args,indexInfo))
  10281. {
  10282. var token=job.Token;
  10283. this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallScriptIndex() ${indexInfo.Name} 指标参数错误 : ${indexInfo.Error} `);
  10284. }
  10285. JSConsole.Complier.Log('[JSSymbolData::CallScriptIndex] call script index', indexInfo);
  10286. var DateTimeRange=null;
  10287. if (this.Data && this.Data.Data.length>0)
  10288. {
  10289. var start=this.Data.Data[0];
  10290. var end=this.Data.Data[this.Data.Data.length-1];
  10291. DateTimeRange=
  10292. {
  10293. Start:{Date:start.Date, Time: start.Time},
  10294. End:{Date:end.Date, Time: end.Time},
  10295. }
  10296. }
  10297. var option=
  10298. {
  10299. HQDataType:this.DataType,
  10300. Symbol:indexInfo.Symbol,
  10301. Name:'',
  10302. Right:this.Right, //复权
  10303. Period:indexInfo.PeriodID, //周期
  10304. Data:null,
  10305. SourceData:null,
  10306. Callback:(outVar,job, symbolData)=> {
  10307. this.RecvScriptIndexData(outVar,job,symbolData);
  10308. this.Execute.RunNextJob();
  10309. },
  10310. CallbackParam:indexInfo,
  10311. Async:true,
  10312. MaxRequestDataCount:this.MaxRequestDataCount+30*2,
  10313. MaxRequestMinuteDayCount:this.MaxRequestMinuteDayCount+2,
  10314. Arguments:indexInfo.Args,
  10315. //Condition:this.Condition,
  10316. IsBeforeData:this.IsBeforeData,
  10317. NetworkFilter:this.NetworkFilter,
  10318. IsApiPeriod:this.IsApiPeriod,
  10319. KLineRange:DateTimeRange //K线数据范围
  10320. };
  10321. //执行脚本
  10322. var run=JSComplier.Execute(indexInfo.SytemIndex.Script,option,(error, indexInfo)=>{this.ExecuteScriptIndexError(error,indexInfo)});
  10323. }
  10324. this.RecvMemberScriptIndexData=function(outVar,indexInfo,symbolData)
  10325. {
  10326. JSConsole.Complier.Log('[JSSymbolData::RecvMemberScriptIndexData] ', outVar, indexInfo, symbolData);
  10327. var kLine=symbolData.Data.Data;
  10328. var aryOutVar=outVar;
  10329. var data=this.Data.FitKLineIndex(kLine,aryOutVar,this.Period,indexInfo.PeriodID);
  10330. var member=indexInfo.Job.Member;
  10331. var objName=member.Object.Name;
  10332. var propertyName=member.Property.Name;
  10333. var memberValue={};
  10334. if (this.Execute.VarTable.has(objName))
  10335. memberValue=this.Execute.VarTable.get(objName);
  10336. else
  10337. this.Execute.VarTable.set(objName, memberValue);
  10338. //保存所有的指标数据, 下面用到了就可以不用算了
  10339. for(var i in data)
  10340. {
  10341. var key=outVar[i].Name;
  10342. if (indexInfo.Period) key+='#'+indexInfo.Period; //带周期的变量
  10343. memberValue[key]=data[i].Data;
  10344. }
  10345. }
  10346. this.RecvScriptIndexData=function(outVar,indexInfo,symbolData)
  10347. {
  10348. var key=this.GenerateScriptIndexKey(indexInfo);
  10349. JSConsole.Complier.Log('[JSSymbolData::RecvScriptIndexData] ', outVar, indexInfo, symbolData, key);
  10350. var kLine=symbolData.Data.Data;
  10351. var aryOutVar=outVar;
  10352. if (indexInfo.Out)
  10353. {
  10354. for(var i=0;i<outVar.length; ++i)
  10355. {
  10356. var item=outVar[i];
  10357. if (item.Name==indexInfo.Out)
  10358. {
  10359. aryOutVar=[item];
  10360. break;
  10361. }
  10362. }
  10363. var data=this.Data.FitKLineIndex(kLine,aryOutVar,this.Period,indexInfo.PeriodID);
  10364. this.ScriptIndexOutData.set(key,data[0].Data);
  10365. }
  10366. else if (IFrameSplitOperator.IsPlusNumber(indexInfo.OutIndex))
  10367. {
  10368. var index=indexInfo.OutIndex-1;
  10369. aryOutVar=[outVar[index]];
  10370. var data=this.Data.FitKLineIndex(kLine,aryOutVar,this.Period,indexInfo.PeriodID);
  10371. this.ScriptIndexOutData.set(key,data[0].Data);
  10372. }
  10373. else
  10374. {
  10375. var data=this.Data.FitKLineIndex(kLine,aryOutVar,this.Period,indexInfo.PeriodID);
  10376. var result={ __Type__:"Object" };
  10377. for(var i in data)
  10378. {
  10379. var item=data[i];
  10380. result[item.Name]=item.Data;
  10381. }
  10382. this.ScriptIndexOutData.set(key,result);
  10383. }
  10384. }
  10385. this.RecvDynamicScriptIndexData=function(outVar,indexInfo,symbolData)
  10386. {
  10387. JSConsole.Complier.Log('[JSSymbolData::RecvDynamicScriptIndexData] ', outVar, indexInfo, symbolData);
  10388. var kLine=symbolData.Data.Data;
  10389. var aryOutVar=outVar;
  10390. var data=this.Data.FitKLineIndex(kLine,aryOutVar,this.Period,indexInfo.PeriodID);
  10391. var objName=indexInfo.Name;
  10392. var memberValue={};
  10393. if (this.Execute.VarTable.has(objName))
  10394. memberValue=this.Execute.VarTable.get(objName);
  10395. else
  10396. this.Execute.VarTable.set(objName, memberValue);
  10397. var strValue="";
  10398. for(var i=0; i<indexInfo.Args.length; ++i)
  10399. {
  10400. var item=indexInfo.Args[i];
  10401. if (item.IsDefault===false)
  10402. {
  10403. if (strValue.length>0) strValue+=",";
  10404. strValue+=`${item.Value}`;
  10405. }
  10406. }
  10407. var strArgs=`(${strValue})`;
  10408. //保存所有的指标数据, 下面用到了就可以不用算了
  10409. for(var i=0; i<data.length; ++i)
  10410. {
  10411. var key=`${outVar[i].Name}#${strArgs}`;
  10412. if (indexInfo.Period) key+='#'+indexInfo.Period; //带周期的变量
  10413. memberValue[key]=data[i].Data;
  10414. }
  10415. }
  10416. //key= (代码,周期),指标(参数) => 输出
  10417. this.GenerateScriptIndexKey=function(indexInfo)
  10418. {
  10419. var indexParam='';
  10420. var args=indexInfo.Args;
  10421. for(var i in args)
  10422. {
  10423. if (indexParam.length>0) indexParam+=',';
  10424. var item=args[i];
  10425. indexParam+=item.Value.toString();
  10426. }
  10427. var out="ALL";
  10428. if (indexInfo.Out) out=indexInfo.Out;
  10429. else if (IFrameSplitOperator.IsPlusNumber(indexInfo.OutIndex)) out=`Out[${indexInfo.OutIndex-1}]`;
  10430. var key=`(${indexInfo.Symbol},${indexInfo.PeriodID}), ${indexInfo.Name}(${indexParam})=>${out}`;
  10431. return key;
  10432. }
  10433. this.ExecuteScriptIndexError=function(error,indexInfo)
  10434. {
  10435. var token=indexInfo.Job.Token;
  10436. this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallScriptIndex() ${indexInfo.Name} 指标执行错误 : ${error} `);
  10437. }
  10438. this.GetScriptIndexOutData=function(args,node, funcName)
  10439. {
  10440. var indexInfo={ PeriodID:this.Period };
  10441. if (!this.ReadSymbolArgumentValue(args[0],indexInfo)) //读取代码
  10442. this.Execute.ThrowUnexpectedNode(node,`${funcName}() 股票代码错误: ${indexInfo.Error}`);
  10443. if (!this.ReadIndexFunctionValue(args[1],indexInfo)) //读取指标
  10444. this.Execute.ThrowUnexpectedNode(node,`${funcName}() 指标错误: ${indexInfo.Error}`);
  10445. if (funcName=="CALCSTOCKINDEX")
  10446. {
  10447. if (!this.ReadIndexFunctionOut(args[2],indexInfo)) //读取返回值索引
  10448. this.Execute.ThrowUnexpectedNode(node, `${funcName}() Error: ${indexInfo.Error}`);
  10449. }
  10450. var systemIndex=new JSIndexScript();
  10451. var systemItem=systemIndex.Get(indexInfo.Name);
  10452. if (!systemItem)
  10453. this.Execute.ThrowUnexpectedNode(node,`${funcName}() 指标错误: ${indexInfo.Name} 指标不存在`);
  10454. indexInfo.SytemIndex=systemItem; //系统指标
  10455. if (!this.ReadIndexArgumentValue(args,indexInfo))
  10456. this.Execute.ThrowUnexpectedNode(node,`${funcName}() 指标参数错误: ${indexInfo.Error}`);
  10457. var key=this.GenerateScriptIndexKey(indexInfo);
  10458. if (!this.ScriptIndexOutData.has(key)) return null;
  10459. return this.ScriptIndexOutData.get(key);
  10460. }
  10461. this.JsonDataToHistoryData=function(data)
  10462. {
  10463. var list = data.data;
  10464. var aryDayData=new Array();
  10465. var date = 0, yclose = 1, open = 2, high = 3, low = 4, close = 5, vol = 6, amount = 7;
  10466. var up = 8, down = 9, stop = 10, unchanged = 11;
  10467. for (var i = 0; i < list.length; ++i)
  10468. {
  10469. var item = new JSCommonData.HistoryData();
  10470. item.Date = list[i][date];
  10471. item.Open = list[i][open];
  10472. item.YClose = list[i][yclose];
  10473. item.Close = list[i][close];
  10474. item.High = list[i][high];
  10475. item.Low = list[i][low];
  10476. item.Vol = list[i][vol]; //原始单位股
  10477. item.Amount = list[i][amount];
  10478. if (isNaN(item.Open) || item.Open<=0) continue; //停牌的数据剔除
  10479. //上涨 下跌家数
  10480. if (list[i].length > up) item.Up = list[i][up];
  10481. if (list[i].length > down) item.Down = list[i][down];
  10482. if (list[i].length > stop) item.Stop = list[i][stop];
  10483. if (list[i].length > unchanged) item.Unchanged = list[i][unchanged];
  10484. aryDayData.push(item);
  10485. }
  10486. return aryDayData;
  10487. }
  10488. this.JsonDataToMinuteHistoryData=function(data)
  10489. {
  10490. var list = data.data;
  10491. var aryDayData=new Array();
  10492. var date = 0, yclose = 1, open = 2, high = 3, low = 4, close = 5, vol = 6, amount = 7, time = 8;
  10493. for (var i = 0; i < list.length; ++i)
  10494. {
  10495. let item = new JSCommonData.HistoryData();
  10496. item.Date = list[i][date];
  10497. item.Open = list[i][open];
  10498. item.YClose = list[i][yclose];
  10499. item.Close = list[i][close];
  10500. item.High = list[i][high];
  10501. item.Low = list[i][low];
  10502. item.Vol = list[i][vol]; //原始单位股
  10503. item.Amount = list[i][amount];
  10504. item.Time=list[i][time];
  10505. // if (isNaN(item.Open) || item.Open<=0) continue; //停牌的数据剔除
  10506. aryDayData.push(item);
  10507. }
  10508. // 无效数据处理
  10509. for(let i = 0; i < aryDayData.length; ++i)
  10510. {
  10511. var minData = aryDayData[i];
  10512. if (minData == null) coninue;
  10513. if (isNaN(minData.Open) || minData.Open <= 0 || isNaN(minData.High) || minData.High <= 0 || isNaN(minData.Low) || minData.Low <= 0
  10514. || isNaN(minData.Close) || minData.Close <= 0 || isNaN(minData.YClose) || minData.YClose <= 0)
  10515. {
  10516. if (i == 0)
  10517. {
  10518. if (minData.YClose > 0)
  10519. {
  10520. minData.Open = minData.YClose;
  10521. minData.High = minData.YClose;
  10522. minData.Low = minData.YClose;
  10523. minData.Close = minData.YClose;
  10524. }
  10525. }
  10526. else // 用前一个有效数据填充
  10527. {
  10528. for(let j = i-1; j >= 0; --j)
  10529. {
  10530. var minData2 = aryDayData[j];
  10531. if (minData2 == null) coninue;
  10532. if (minData2.Open > 0 && minData2.High > 0 && minData2.Low > 0 && minData2.Close > 0)
  10533. {
  10534. if (minData.YClose <= 0) minData.YClose = minData2.Close;
  10535. minData.Open = minData2.Open;
  10536. minData.High = minData2.High;
  10537. minData.Low = minData2.Low;
  10538. minData.Close = minData2.Close;
  10539. break;
  10540. }
  10541. }
  10542. }
  10543. }
  10544. }
  10545. return aryDayData;
  10546. }
  10547. //API 返回数据 转化为array[]
  10548. this.JsonDataToMinuteData = function (data)
  10549. {
  10550. var aryMinuteData = new Array();
  10551. for (var i in data.stock[0].minute)
  10552. {
  10553. var jsData = data.stock[0].minute[i];
  10554. var item = new JSCommonData.MinuteData();
  10555. item.Close = jsData.price;
  10556. item.Open = jsData.open;
  10557. item.High = jsData.high;
  10558. item.Low = jsData.low;
  10559. item.Vol = jsData.vol; //股
  10560. item.Amount = jsData.amount;
  10561. if (i == 0) //第1个数据 写死9:25
  10562. item.DateTime = data.stock[0].date.toString() + " 0925";
  10563. else
  10564. item.DateTime = data.stock[0].date.toString() + " " + jsData.time.toString();
  10565. item.Date = data.stock[0].date;
  10566. item.Time = jsData.time;
  10567. item.Increate = jsData.increate;
  10568. item.Risefall = jsData.risefall;
  10569. item.AvPrice = jsData.avprice;
  10570. aryMinuteData[i] = item;
  10571. }
  10572. return aryMinuteData;
  10573. }
  10574. //CODELIKE 模糊股票代码
  10575. this.CODELIKE=function(value)
  10576. {
  10577. if (this.Symbol.indexOf(value)==0) return 1;
  10578. return 0;
  10579. }
  10580. this.NAMELIKE = function (value)
  10581. {
  10582. if (this.Name && this.Name.indexOf(value) == 0) return 1;
  10583. return 0;
  10584. }
  10585. /*
  10586. SETCODE 市场类型
  10587. 0:深圳 1:上海,47:中金所期货 28:郑州商品 29:大连商品 30:上海商品,27:香港指数 31:香港主板,48:香港创业板...
  10588. */
  10589. this.SETCODE=function()
  10590. {
  10591. if (this.Symbol.indexOf('.sh')) return 1;
  10592. if (this.Symbol.indexOf('.sz')) return 0;
  10593. return 0;
  10594. }
  10595. this.GetSymbol = function () { return this.Symbol; }
  10596. this.GetName = function () { return this.Name; }
  10597. this.TIME=function()
  10598. {
  10599. var result = [];
  10600. if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result;
  10601. for(let i in this.Data.Data)
  10602. {
  10603. var item=this.Data.Data[i];
  10604. if (this.IsNumber(item.Time))
  10605. result[i]=item.Time;
  10606. else
  10607. result[i]=0;
  10608. }
  10609. return result;
  10610. }
  10611. this.DATE = function ()
  10612. {
  10613. var result = [];
  10614. if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result;
  10615. for (let i in this.Data.Data)
  10616. {
  10617. var item = this.Data.Data[i];
  10618. result[i] = item.Date - 19000000;;
  10619. }
  10620. return result;
  10621. }
  10622. /*
  10623. 取得该周期的时分秒,适用于日线以下周期.
  10624. 用法: TIME2
  10625. 函数返回有效值范围为(000000-235959)
  10626. */
  10627. this.TIME2=function()
  10628. {
  10629. var result=[];
  10630. if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result;
  10631. for(let i=0;i<this.Data.Data.length;++i)
  10632. {
  10633. var item=this.Data.Data[i];
  10634. if (this.IsNumber(item.Time))
  10635. result[i]=item.Time*100;
  10636. else
  10637. result[i]=0;
  10638. }
  10639. return result;
  10640. }
  10641. this.DateTime=function()
  10642. {
  10643. var result=[];
  10644. if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result;
  10645. var isKLineMinute=ChartData.IsMinutePeriod(this.Period, true);
  10646. for(var i=0;i<this.Data.Data.length;++i)
  10647. {
  10648. var item=this.Data.Data[i];
  10649. if (isKLineMinute)
  10650. {
  10651. result[i]=item.Date*10000+item.Time;
  10652. }
  10653. else
  10654. {
  10655. result[i]=item.Date;
  10656. }
  10657. }
  10658. return result;
  10659. }
  10660. this.YEAR = function ()
  10661. {
  10662. var result = [];
  10663. if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result;
  10664. for (let i in this.Data.Data)
  10665. {
  10666. var item = this.Data.Data[i];
  10667. if (this.IsNumber(item.Date))
  10668. result[i] = parseInt(item.Date / 10000);
  10669. else
  10670. result[i] = null;
  10671. }
  10672. return result;
  10673. }
  10674. this.MONTH = function ()
  10675. {
  10676. var result = [];
  10677. if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result;
  10678. for (let i in this.Data.Data)
  10679. {
  10680. var item = this.Data.Data[i];
  10681. if (this.IsNumber(item.Date))
  10682. result[i] = parseInt(item.Date % 10000 / 100);
  10683. else
  10684. result[i] = null;
  10685. }
  10686. return result;
  10687. }
  10688. //星期 1-7
  10689. this.WEEK = function ()
  10690. {
  10691. var result = [];
  10692. if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result;
  10693. var tempDate = new Date();
  10694. for (let i in this.Data.Data)
  10695. {
  10696. var item = this.Data.Data[i];
  10697. result[i] = null;
  10698. if (!this.IsNumber(item.Date)) continue;
  10699. var year = parseInt(item.Date / 10000);
  10700. var month = parseInt(item.Date % 10000 / 100);
  10701. var day = item.Date % 100;
  10702. tempDate.setFullYear(year, month - 1, day);
  10703. result[i] = tempDate.getDay();
  10704. }
  10705. return result;
  10706. }
  10707. /*
  10708. 取得该周期的日期离今天的天数.
  10709. 用法: DAYSTOTODAY
  10710. */
  10711. this.DAYSTOTODAY=function()
  10712. {
  10713. var result=[];
  10714. if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result;
  10715. var nowDate=new Date();
  10716. var endDate=new Date(nowDate.getFullYear(), nowDate.getMonth(), nowDate.getDate());
  10717. for(let i=0; i<this.Data.Data.length; ++i)
  10718. {
  10719. var item=this.Data.Data[i];
  10720. result[i]=null;
  10721. if (!this.IsNumber(item.Date)) continue;
  10722. var year=parseInt(item.Date/10000);
  10723. var month=parseInt(item.Date%10000/100);
  10724. var day=item.Date%100;
  10725. var beginDate=new Date(year,month-1,day);
  10726. var diffDays = Math.ceil((endDate - beginDate)/(24*60*60*1000));
  10727. result[i]=diffDays;
  10728. }
  10729. return result;
  10730. }
  10731. /*
  10732. 取得该周是年内第几个周.
  10733. 用法:WEEKOFYEAR
  10734. */
  10735. this.WEEKOFYEAR=function()
  10736. {
  10737. var result=[];
  10738. if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result;
  10739. for(let i in this.Data.Data)
  10740. {
  10741. var item=this.Data.Data[i];
  10742. result[i]=null;
  10743. if (!this.IsNumber(item.Date)) continue;
  10744. var year=parseInt(item.Date/10000);
  10745. var month=parseInt(item.Date%10000/100);
  10746. var day=item.Date%100;
  10747. var endDate=new Date(year,month-1,day);
  10748. var beginDate=new Date(year,0,1);
  10749. var diffDays = Math.ceil((endDate - beginDate)/(24*60*60*1000));
  10750. diffDays+=((beginDate.getDay() + 1) - 1);
  10751. var week = Math.ceil(diffDays/7);
  10752. var value=week;
  10753. result[i]=value;
  10754. }
  10755. return result;
  10756. }
  10757. this.GetYearWeek=function(endDate)
  10758. {
  10759. var beginDate = new Date(endDate.getFullYear(), 0, 1);
  10760. //星期从0-6,0代表星期天,6代表星期六
  10761. var endWeek = endDate.getDay();
  10762. if (endWeek == 0) endWeek = 7;
  10763. var beginWeek = beginDate.getDay();
  10764. if (beginWeek == 0) beginWeek = 7;
  10765. //计算两个日期的天数差
  10766. var millisDiff = endDate.getTime() - beginDate.getTime();
  10767. var dayDiff = Math.floor(( millisDiff + (beginWeek - endWeek) * (24 * 60 * 60 * 1000)) / 86400000);
  10768. return Math.ceil(dayDiff / 7) + 1;
  10769. }
  10770. this.REFDATE = function (data, date)
  10771. {
  10772. var result = null;
  10773. var findDate=null;
  10774. if (Array.isArray(date))
  10775. {
  10776. if (date.length>0) findDate=date[date.length-1];
  10777. }
  10778. else if (this.IsNumber(date))
  10779. {
  10780. findDate=date;
  10781. }
  10782. if (findDate==null) return null;
  10783. if (findDate<5000000) findDate+=19000000;
  10784. var index = null;
  10785. for (let i in this.Data.Data) //查找日期对应的索引
  10786. {
  10787. if (this.Data.Data[i].Date == findDate)
  10788. {
  10789. index = parseInt(i);
  10790. break;
  10791. }
  10792. }
  10793. if (index == null || index >= data.length) return null;
  10794. return data[index];
  10795. }
  10796. //用法:结果从0到11,依次分别是1/5/15/30/60分钟,日/周/月,多分钟,多日,季,年
  10797. this.PERIOD=function()
  10798. {
  10799. //Period周期 0=日线 1=周线 2=月线 3=年线 9=季线 4=1分钟 5=5分钟 6=15分钟 7=30分钟 8=60分钟
  10800. const PERIOD_MAP=[5,6,7,11, 0,1,2,3,4,5, 9];
  10801. if (this.Period >= 0 && this.Period <= PERIOD_MAP.length - 1)
  10802. return PERIOD_MAP[this.Period];
  10803. return this.Period;
  10804. }
  10805. this.GetDrawNull = function ()
  10806. {
  10807. var result = [];
  10808. if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result;
  10809. for (let i in this.Data.Data)
  10810. {
  10811. result[i] = null;
  10812. }
  10813. return result;
  10814. }
  10815. this.HOUR=function()
  10816. {
  10817. var result=[];
  10818. if (!this.Data || !this.Data.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return result;
  10819. for(var i=0;i<this.Data.Data.length;++i)
  10820. {
  10821. var item=this.Data.Data[i];
  10822. result[i]=0;
  10823. if (IFrameSplitOperator.IsNumber(item.Time)) result[i]=parseInt(item.Time/100);
  10824. }
  10825. return result;
  10826. }
  10827. this.MINUTE=function()
  10828. {
  10829. var result=[];
  10830. if (!this.Data || !this.Data.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return result;
  10831. for(var i=0;i<this.Data.Data.length;++i)
  10832. {
  10833. var item=this.Data.Data[i];
  10834. result[i]=0;
  10835. if (IFrameSplitOperator.IsNumber(item.Time)) result[i]=item.Time%100;
  10836. }
  10837. return result;
  10838. }
  10839. }
  10840. //是否有是有效的数字
  10841. JSSymbolData.prototype.IsNumber = function (value)
  10842. {
  10843. if (value == null) return false;
  10844. if (isNaN(value)) return false;
  10845. return true;
  10846. }
  10847. JSSymbolData.prototype.IsDivideNumber = function (value)
  10848. {
  10849. if (value == null) return false;
  10850. if (isNaN(value)) return false;
  10851. if (value == 0) return false;
  10852. return true;
  10853. }
  10854. JSSymbolData.prototype.JsonDataToFinance = function (data)
  10855. {
  10856. var financeData;
  10857. for (let i = 1; i <= 4; ++i)
  10858. {
  10859. switch (i)
  10860. {
  10861. case 1:
  10862. var finance = data.finance1;
  10863. var announcement = data.announcement1;
  10864. break;
  10865. case 2:
  10866. var finance = data.finance2;
  10867. var announcement = data.announcement2;
  10868. break;
  10869. case 3:
  10870. var finance = data.finance3;
  10871. var announcement = data.announcement3;
  10872. break;
  10873. case 4:
  10874. var finance = data.finance4;
  10875. var announcement = data.announcement4;
  10876. break;
  10877. default:
  10878. break;
  10879. }
  10880. if (!finance || !announcement || !this.IsNumber(announcement.year) || !this.IsNumber(announcement.quarter)) continue;
  10881. if (financeData) //如果存在1天公布多个报告期数据 只取最新的一个公告期数据
  10882. {
  10883. if (financeData.Announcement.year < announcement.year)
  10884. financeData = { Date: data.date, Finance: finance, Announcement: announcement };
  10885. }
  10886. else
  10887. {
  10888. financeData = { Date: data.date, Finance: finance, Announcement: announcement };
  10889. }
  10890. }
  10891. return financeData;
  10892. }
  10893. var JS_EXECUTE_DEBUG_LOG=false;
  10894. var JS_EXECUTE_JOB_ID=
  10895. {
  10896. JOB_DOWNLOAD_SYMBOL_DATA:1, //下载股票的K线数据
  10897. JOB_DOWNLOAD_INDEX_DATA:2, //下载大盘的K线数据
  10898. JOB_DOWNLOAD_SYMBOL_LATEST_DATA:3, //最新的股票行情数据
  10899. JOB_DOWNLOAD_INDEX_INCREASE_DATA: 4, //涨跌股票个数统计数据
  10900. JOB_DOWNLOAD_VOLR_DATA: 5, //5日量比均量下载量比数据
  10901. JOB_DOWNLOAD_OTHER_SYMBOL_DATA:9, //下载其他股票的K线数据
  10902. JOB_DOWNLOAD_FINVALUE:301, //引用专业财务数据 FINVALUE(ID),ID为数据编号
  10903. JOB_DOWNLOAD_FINONE:302, //引用指定年和月日的某类型的财务数据 FINONE(ID,Y,MMDD),ID为数据编号,Y和MMDD表示年和月日.
  10904. JOB_DOWNLOAD_FINANCE:303, //FINANCE(ID) 基础财务数据
  10905. JOB_DOWNLOAD_GPJYVALUE:304, //引用股票交易类数据 GPJYVALUE(ID,N,TYPE),ID为数据编号,N表示第几个数据,TYPE:为1表示做平滑处理,没有数据的周期返回上一周期的值;为0表示不做平滑处理
  10906. JOB_DOWNLOAD_VARIANT:305, //CAPITAL , TOTALCAPITAL, EXCHANGE
  10907. JOB_DOWNLOAD_SCJYVALUE:306, //引用市场总的交易类数据.SCJYVALUE(ID,N,TYPE),ID为数据编号,N表示第几个数据,TYPE:为1表示做平滑处理,没有数据的周期返回上一周期的值;为0表示不做平滑处理
  10908. JOB_DOWNLOAD_GPJYONE:307, //GPJYONE(ID,N,Y,MMDD),ID为数据编号,N表示第几个数据(取1或2),Y和MMDD表示年和月日. 如果Y为0,MMDD为0,表示最新数据,MMDD为1,2,3...,表示倒数第2,3,4...个数据
  10909. JOB_DOWNLOAD_SCJYONE:308, //SCJYONE(ID,N,Y,MMDD),ID为数据编号,N表示第几个数据(取1或2),Y和MMDD表示年和月日.如果Y为0,MMDD为0,表示最新数据,MMDD为1,2,3...,表示倒数第2,3,4...个数据
  10910. JOB_DOWNLOAD_BKJYVALUE:309, //BKJYVALUE(ID,N,TYPE),ID为数据编号,N表示第几个数据(取1或2),TYPE:为1表示做平滑处理,没有数据的周期返回上一周期的值;为0表示不做平滑处理;2表示没有数据则为0.
  10911. JOB_DOWNLOAD_BKJYONE:310, //BKJYONE(ID,N,Y,MMDD),ID为数据编号,N表示第几个数据(取1或2),Y和MMDD表示年和月日.如果Y为0,MMDD为0,表示最新数据,MMDD为1,2,3...,表示倒数第2,3,4...个数据
  10912. JOB_CUSTOM_FUNCTION_DATA:6000, //自定义函数
  10913. JOB_CUSTOM_VARIANT_DATA:6001, //自定义变量
  10914. JOB_CUSTOM_DATA_FUNCTION:6002, //自定义数据函数
  10915. JOB_DOWNLOAD_MARGIN_BALANCE: 1000, //融资融券余额
  10916. JOB_DOWNLOAD_MARGIN_RATE: 1001, //融资占比
  10917. JOB_DOWNLOAD_MARGIN_BUY_BALANCE: 1010, //买入信息-融资余额
  10918. JOB_DOWNLOAD_MARGIN_BUY_AMOUNT: 1011, //买入信息-买入额
  10919. JOB_DOWNLOAD_MARGIN_BUY_REPAY: 1012, //买入信息-偿还额
  10920. JOB_DOWNLOAD_MARGIN_BUY_NET: 1013, //买入信息-融资净买入
  10921. JOB_DOWNLOAD_MARGIN_SELL_BALANCE: 1020, //卖出信息-融券余量
  10922. JOB_DOWNLOAD_MARGIN_SELL_VOLUME: 1021, //卖出信息-卖出量
  10923. JOB_DOWNLOAD_MARGIN_SELL_REPAY: 1022, //卖出信息-偿还量
  10924. JOB_DOWNLOAD_MARGIN_SELL_NET: 1023, //卖出信息-融券净卖出
  10925. JOB_DOWNLOAD_NEWS_ANALYSIS_NEGATIVE: 2000, //负面新闻统计
  10926. JOB_DOWNLOAD_NEWS_ANALYSIS_RESEARCH: 2001, //机构调研
  10927. JOB_DOWNLOAD_NEWS_ANALYSIS_INTERACT: 2002, //互动易
  10928. JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE: 2003, //股东增持
  10929. JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE2: 2004, //股东减持
  10930. JOB_DOWNLOAD_NEWS_ANALYSIS_TRUSTHOLDER: 2005, //信托持股
  10931. JOB_DOWNLOAD_NEWS_ANALYSIS_BLOCKTRADING: 2006, //大宗交易
  10932. JOB_DOWNLOAD_NEWS_ANALYSIS_COMPANYNEWS: 2007, //官网新闻
  10933. JOB_DOWNLOAD_NEWS_ANALYSIS_TOPMANAGERS: 2008, //高管要闻
  10934. JOB_DOWNLOAD_NEWS_ANALYSIS_PLEDGE: 2009, //股权质押
  10935. JOB_DOWNLOAD_CUSTOM_API_DATA: 30000, //自定义数据
  10936. //调用其他脚本指标
  10937. //KDJ.K , KDJ.K#WEEK
  10938. //STKINDI('600000.sh','MA.MA1#WEEK',5,10,20,30,60,120);
  10939. JOB_EXECUTE_INDEX:30010,
  10940. JOB_RUN_SCRIPT:10000, //执行脚本
  10941. //融资融券
  10942. GetMarginJobID: function (value)
  10943. {
  10944. let dataMap = new Map([
  10945. [1, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BALANCE], //MARGIN(1) 融资融券余额
  10946. [2, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_RATE], //MARGIN(2) 融资占比
  10947. [3, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_BALANCE], //MARGIN(3) 买入信息-融资余额
  10948. [4, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_AMOUNT], //MARGIN(4) 买入信息-买入额
  10949. [5, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_REPAY], //MARGIN(5) 买入信息-偿还额
  10950. [6, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_NET], //MARGIN(6) 买入信息-融资净买入
  10951. [7, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_BALANCE], //MARGIN(7) 卖出信息-融券余量
  10952. [8, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_VOLUME], //MARGIN(8) 卖出信息-卖出量
  10953. [9, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_REPAY], //MARGIN(9) 卖出信息-偿还量
  10954. [10, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_NET], //MARGIN(10) 卖出信息-融券净卖出
  10955. ]);
  10956. if (dataMap.has(value)) return dataMap.get(value);
  10957. return null;
  10958. },
  10959. GetNewsAnalysisID: function (value)
  10960. {
  10961. let dataMap = new Map([
  10962. [1, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_NEGATIVE], //NEWS(1) 负面新闻统计
  10963. [2, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_RESEARCH], //NEWS(2) 机构调研统计
  10964. [3, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_INTERACT], //NEWS(3) 互动易
  10965. [4, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE], //NEWS(4) 股东增持
  10966. [5, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE2], //NEWS(5) 股东减持
  10967. [6, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_TRUSTHOLDER], //NEWS(6) 信托持股
  10968. [7, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_BLOCKTRADING], //NEWS(7) 大宗交易
  10969. [8, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_COMPANYNEWS], //NEWS(8) 官网新闻
  10970. [9, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_TOPMANAGERS], //NEWS(9) 高管要闻
  10971. [10, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_PLEDGE], //NEWS(10) 股权质押
  10972. ]);
  10973. if (dataMap.has(value)) return dataMap.get(value);
  10974. return null;
  10975. }
  10976. };
  10977. //专业财务数据
  10978. var JS_ARRAY_PROFESSIONAL_FINANCE=
  10979. [
  10980. {
  10981. Name:"GPJYVALUE", JobID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_GPJYVALUE,
  10982. Explain:"股票交易类数据GPJYVALUE(ID,N,TYPE)", FuncName:"JSSymbolData::GetGPJYValue", ArgCount:3
  10983. },
  10984. {
  10985. Name:"GPJYONE", JobID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_GPJYONE,
  10986. Explain:"股票交易类数据GPJYONE(ID,N,Y,MMDD)", FuncName:"JSSymbolData::GetGPJYOne", ArgCount:4
  10987. },
  10988. {
  10989. Name:"SCJYVALUE", JobID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SCJYVALUE,
  10990. Explain:"市场交易类数据SCJYVALUE(ID,N,TYPE)", FuncName:"JSSymbolData::GetSCJYValue",ArgCount:3
  10991. },
  10992. {
  10993. Name:"SCJYONE", JobID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SCJYONE,
  10994. Explain:"市场交易类数据SCJYONE(ID,N,Y,MMDD)", FuncName:"JSSymbolData::GetSCJYOne",ArgCount:4
  10995. },
  10996. {
  10997. Name:"BKJYVALUE", JobID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_BKJYVALUE,
  10998. Explain:"板块交易类数据BKJYVALUE(ID,N,TYPE)", FuncName:"JSSymbolData::GetBKJYValue",ArgCount:3
  10999. },
  11000. {
  11001. Name:"BKJYONE", JobID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_BKJYONE,
  11002. Explain:"板块交易类数据BKJYONE(ID,N,Y,MMDD)", FuncName:"JSSymbolData::GetBKJYOne",ArgCount:4
  11003. },
  11004. {
  11005. Name:"FINVALUE", JobID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_FINVALUE,
  11006. Explain:"财务数据FINVALUE(ID)", FuncName:"JSSymbolData::GetFinValue",ArgCount:1
  11007. },
  11008. {
  11009. Name:"FINONE", JobID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_FINONE,
  11010. Explain:"财务数据FINONE(ID,Y,MMDD)", FuncName:"JSSymbolData::GetFinOne",ArgCount:3
  11011. }
  11012. ];
  11013. function JSExecute(ast,option)
  11014. {
  11015. this.AST=ast; //语法树
  11016. this.ErrorHandler=new ErrorHandler();
  11017. this.VarTable=new Map(); //变量表
  11018. this.VarDrawTable=new Map(); //绘图变量表
  11019. this.OutVarTable=new Array(); //输出变量
  11020. this.Arguments=[];
  11021. //脚本自动变量表, 只读
  11022. this.ConstVarTable=new Map([
  11023. //个股数据
  11024. ['CLOSE', null], ['VOL', null], ['OPEN', null], ['HIGH', null], ['LOW', null], ['AMOUNT', null], ['AMO', null],
  11025. ['C', null], ['V', null], ['O', null], ['H', null], ['L', null],
  11026. ['VOLR', null],
  11027. ['VOLINSTK',null], ["OPI",null], //持仓量
  11028. ["QHJSJ",null], ["SETTLE",null], //结算价
  11029. ["ZSTJJ",null], //分时图均价线,对于分时图周期指标有效.
  11030. ["ISEQUAL",null], ["ISUP",null],["ISDOWN"], //ISUP=收阳 ISEQUAL=平盘 ISDOWN=收阴
  11031. //日期类
  11032. ['DATE', null], ['YEAR', null], ['MONTH', null], ['PERIOD', null], ['WEEK', null],['WEEKDAY',null],["TIME",null],["DATETIME",null],["TIME2",null],
  11033. ["WEEKOFYEAR", null],["DAYSTOTODAY", null],
  11034. ["HOUR",null],["MINUTE",null],
  11035. //大盘数据
  11036. ['INDEXA',null],['INDEXC',null],['INDEXH',null],['INDEXL',null],['INDEXO',null],['INDEXV',null],
  11037. ['INDEXADV', null], ['INDEXDEC', null],
  11038. ['FROMOPEN',null], //已开盘有多长分钟
  11039. ['TOTALFZNUM', null], //该品种的每天的总交易分钟数.
  11040. ['CURRBARSCOUNT', null], //到最后交易日的周期数
  11041. ['TOTALBARSCOUNT',null],
  11042. ['ISLASTBAR', null], //判断是否为最后一个周期
  11043. ['BARSTATUS',null], //BARSTATUS返回数据位置信息,1表示第一根K线,2表示最后一个数据,0表示中间位置.
  11044. ["BARPOS", null], //返回从第一根K线开始到当前的周期数
  11045. ["TOTALCAPITAL",null], //总股本
  11046. ['CAPITAL', null], //流通股本(手)
  11047. ['EXCHANGE', null], //换手率
  11048. ['SETCODE', null], //市场类型
  11049. ['CODE', null], //品种代码
  11050. ['STKNAME', null], //品种名称
  11051. ["TQFLAG",null], //TQFLAG 当前的复权状态,0:无复权 1:前复权 2:后复权
  11052. ['HYBLOCK', null], //所属行业板块
  11053. ['DYBLOCK', null], //所属地域板块
  11054. ['GNBLOCK', null], //所属概念
  11055. ["FGBLOCK",null], //所属风格板块
  11056. ["ZSBLOCK",null], //所属指数板块
  11057. ["ZHBLOCK",null], //所属组合板块
  11058. ["ZDBLOCK",null], //所属自定义板块
  11059. ["HYZSCODE",null],
  11060. ["GNBLOCKNUM",null], //所属概念板块的个数
  11061. ["FGBLOCKNUM",null], //所属风格板块的个数
  11062. ["ZSBLOCKNUM",null], //所属指数板块的个数
  11063. ["ZHBLOCKNUM",null], //所属组合板块的个数
  11064. ["ZDBLOCKNUM",null], //所属自定义板块的个数
  11065. ["HYSYL",null], //指数市盈率或个股所属行业的市盈率
  11066. ["HYSJL",null], //指数市净率或个股所属行业的市净率
  11067. ['DRAWNULL', null],
  11068. ["NULL",null],
  11069. ["MACHINEDATE",null],["MACHINETIME",null],["MACHINEWEEK",null],
  11070. ['LARGEINTRDVOL', null], //逐笔买入大单成交量,相当于L2_VOL(0,0)+L2_VOL(1,0),沪深京品种的资金流向,仅日线以上周期,用于特定版本
  11071. ['LARGEOUTTRDVOL', null], //逐笔卖出大单成交量,相当于L2_VOL(0,1)+L2_VOL(1,1),沪深京品种的资金流向,仅日线以上周期,用于特定版本
  11072. ["TRADENUM", null], //逐笔成交总单数,沪深京品种的资金流向,仅日线以上周期,用于特定版本
  11073. ["TRADEINNUM", null], //逐笔买入成交单数,相当于L2_VOLNUM(0,0)+L2_VOLNUM(1,0),沪深京品种的资金流向,仅日线以上周期,用于特定版本
  11074. ["TRADEOUTNUM", null], //逐笔卖出成交单数,相当于L2_VOLNUM(0,1)+L2_VOLNUM(1,1),沪深京品种的资金流向,仅日线以上周期,用于特定版本
  11075. ["LARGETRDINNUM", null], //逐笔买入大单成交单数,相当于L2_VOLNUM(0,0),沪深京品种的资金流向,仅日线以上周期,用于特定版本
  11076. ["LARGETRDOUTNUM", null], //逐笔卖出大单成交单数,相当于L2_VOLNUM(0,1),沪深京品种的资金流向,仅日线以上周期,用于特定版本
  11077. ["CUR_BUYORDER", null], //总委买量,序列数据,专业版等(资金流向功能)沪深京品种行情专用
  11078. ["CUR_SELLORDER", null], //总委卖量,序列数据,专业版等(资金流向功能)沪深京品种行情专用
  11079. ["ACTINVOL", null], //主动买成交量,相当于L2_VOL(0,2)+L2_VOL(1,2)+L2_VOL(2,2)+L2_VOL(3,2),沪深京品种的资金流向,仅日线以上周期,用于特定版本
  11080. ["ACTOUTVOL", null], //主动卖成交量,相当于L2_VOL(0,3)+L2_VOL(1,3)+L2_VOL(2,3)+L2_VOL(3,3),沪深京品种的资金流向,仅日线以上周期,用于特定版本
  11081. ["BIDORDERVOL", null], //累计总有效委买量,专业版等(资金流向功能)沪深京品种行情专用 累计总有效委买量-累计总有效撤买量=总买+总成交量
  11082. ["BIDCANCELVOL", null], //累计总有效撤买量,专业版等(资金流向功能)沪深京品种行情专用 累计总有效委买量-累计总有效撤买量=总买+总成交量
  11083. ["AVGBIDPX", null], //专业版等(资金流向功能)沪深京品种行情专用:最新委买均价
  11084. ["OFFERORDERVOL", null], //累计总有效委卖量,专业版等(资金流向功能)沪深京品种行情专用 累计总有效委卖量-累计总有效撤卖量=总卖+总成交量
  11085. ["OFFERCANCELVOL", null], //累计总有效撤卖量,专业版等(资金流向功能)沪深京品种行情专用 累计总有效委卖量-累计总有效撤卖量=总卖+总成交量
  11086. ["AVGOFFERPX", null], //专业版等(资金流向功能)沪深京品种行情专用:最新委卖均价
  11087. ]);
  11088. this.SymbolData=new JSSymbolData(this.AST,option,this);
  11089. this.Algorithm = new JSAlgorithm(this.ErrorHandler, this.SymbolData);
  11090. this.Draw = new JSDraw(this.ErrorHandler, this.SymbolData);
  11091. this.JobList=[]; //执行的任务队列
  11092. this.UpdateUICallback=null; //回调
  11093. this.CallbackParam=null;
  11094. this.Interrupt={ Exit:false }; //中断信息
  11095. if (option)
  11096. {
  11097. if (option.Callback) this.UpdateUICallback=option.Callback;
  11098. if (option.CallbackParam) this.CallbackParam=option.CallbackParam;
  11099. if (option.Arguments) this.Arguments=option.Arguments;
  11100. }
  11101. this.Execute=function()
  11102. {
  11103. JSConsole.Complier.Log('[JSExecute::Execute] JobList', this.JobList);
  11104. this.RunNextJob();
  11105. }
  11106. this.RunNextJob=function()
  11107. {
  11108. if (this.JobList.length<=0) return;
  11109. var jobItem=this.JobList.shift();
  11110. switch (jobItem.ID)
  11111. {
  11112. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SYMBOL_DATA:
  11113. return this.SymbolData.GetSymbolData();
  11114. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_INDEX_DATA:
  11115. return this.SymbolData.GetIndexData();
  11116. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_INDEX_INCREASE_DATA:
  11117. return this.SymbolData.GetIndexIncreaseData(jobItem);
  11118. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SYMBOL_LATEST_DATA:
  11119. return this.SymbolData.GetLatestData(jobItem);
  11120. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_VOLR_DATA: //量比
  11121. return this.SymbolData.GetVolRateData(jobItem);
  11122. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_OTHER_SYMBOL_DATA: //指定股票数据
  11123. return this.SymbolData.GetOtherSymbolData(jobItem);
  11124. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_FINANCE:
  11125. return this.SymbolData.GetFinance(jobItem);
  11126. //专业财务数据
  11127. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_FINONE:
  11128. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_FINVALUE:
  11129. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_GPJYVALUE:
  11130. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_GPJYONE:
  11131. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SCJYVALUE:
  11132. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SCJYONE:
  11133. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_BKJYVALUE:
  11134. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_BKJYONE:
  11135. return this.SymbolData.GetProFinance(jobItem);
  11136. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_VARIANT: //CAPITAL, TOTALCAPITAL
  11137. return this.SymbolData.GetVariantData(jobItem);
  11138. case JS_EXECUTE_JOB_ID.JOB_CUSTOM_VARIANT_DATA:
  11139. return this.SymbolData.GetCustomVariantData(jobItem);
  11140. case JS_EXECUTE_JOB_ID.JOB_CUSTOM_FUNCTION_DATA:
  11141. return this.SymbolData.GetCustomFunctionData(jobItem);
  11142. case JS_EXECUTE_JOB_ID.JOB_CUSTOM_DATA_FUNCTION:
  11143. return this.SymbolData.GetCustomFunctionDataV2(jobItem);
  11144. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BALANCE:
  11145. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_RATE:
  11146. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_BALANCE: //买入信息-融资余额
  11147. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_AMOUNT: //买入信息-买入额
  11148. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_REPAY: //买入信息-偿还额
  11149. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_NET: //买入信息-融资净买入
  11150. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_BALANCE: //卖出信息-融券余量
  11151. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_VOLUME: //卖出信息-卖出量
  11152. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_REPAY: //卖出信息-偿还量
  11153. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_NET: //卖出信息-融券净卖出
  11154. return this.SymbolData.GetMarginData(jobItem.ID);
  11155. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_NEGATIVE: //负面新闻
  11156. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_RESEARCH: //机构调研
  11157. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_INTERACT: //互动易
  11158. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE: //股东增持
  11159. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE2: //股东减持
  11160. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_TRUSTHOLDER: //信托持股
  11161. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_BLOCKTRADING: //大宗交易
  11162. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_COMPANYNEWS: //官网新闻
  11163. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_TOPMANAGERS: //高管要闻
  11164. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_PLEDGE: //股权质押
  11165. return this.SymbolData.GetNewsAnalysisData(jobItem.ID);
  11166. case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_CUSTOM_API_DATA:
  11167. return this.SymbolData.DownloadCustomAPIData(jobItem);
  11168. case JS_EXECUTE_JOB_ID.JOB_EXECUTE_INDEX:
  11169. return this.SymbolData.CallScriptIndex(jobItem, this.VarTable);
  11170. case JS_EXECUTE_JOB_ID.JOB_RUN_SCRIPT:
  11171. return this.Run();
  11172. }
  11173. }
  11174. this.ReadSymbolData=function(name,node)
  11175. {
  11176. switch(name)
  11177. {
  11178. case 'CLOSE':
  11179. case 'C':
  11180. case 'VOL':
  11181. case 'V':
  11182. case 'OPEN':
  11183. case 'O':
  11184. case 'HIGH':
  11185. case 'H':
  11186. case 'LOW':
  11187. case 'L':
  11188. case 'AMOUNT':
  11189. case "OPI":
  11190. case 'VOLINSTK':
  11191. case "SETTLE":
  11192. case "QHJSJ":
  11193. case "ZSTJJ":
  11194. case "ISEQUAL": //平盘
  11195. case "ISUP": //收阳
  11196. case "ISDOWN": //收阴
  11197. return this.SymbolData.GetSymbolCacheData(name);
  11198. case 'VOLR':
  11199. return this.SymbolData.GetVolRateCacheData(node);
  11200. //大盘数据
  11201. case 'INDEXA':
  11202. case 'INDEXC':
  11203. case 'INDEXH':
  11204. case 'INDEXO':
  11205. case 'INDEXV':
  11206. case 'INDEXL':
  11207. case 'INDEXADV':
  11208. case 'INDEXDEC':
  11209. return this.SymbolData.GetIndexCacheData(name);
  11210. case 'CURRBARSCOUNT':
  11211. return this.SymbolData.GetCurrBarsCount();
  11212. case "BARPOS":
  11213. return this.SymbolData.GetBarPos();
  11214. case "TOTALBARSCOUNT":
  11215. return this.SymbolData.GetTotalBarsCount();
  11216. case "TOTALFZNUM":
  11217. return this.SymbolData.GetTotalTradeMinuteCount();
  11218. case 'ISLASTBAR':
  11219. return this.SymbolData.GetIsLastBar();
  11220. case "BARSTATUS":
  11221. return this.SymbolData.GetBarStatus();
  11222. case "TOTALCAPITAL":
  11223. case 'CAPITAL':
  11224. case 'EXCHANGE':
  11225. case "HYBLOCK":
  11226. case "DYBLOCK":
  11227. case "GNBLOCK":
  11228. case "FGBLOCK":
  11229. case "ZSBLOCK":
  11230. case "ZHBLOCK":
  11231. case "ZDBLOCK":
  11232. case "HYZSCODE":
  11233. case "GNBLOCKNUM":
  11234. case "FGBLOCKNUM":
  11235. case "ZSBLOCKNUM":
  11236. case "ZHBLOCKNUM":
  11237. case "ZDBLOCKNUM":
  11238. case "HYSYL":
  11239. case "HYSJL":
  11240. case 'FROMOPEN':
  11241. case "LARGEINTRDVOL":
  11242. case "LARGEOUTTRDVOL":
  11243. case "TRADENUM":
  11244. case "TRADEINNUM":
  11245. case "TRADEOUTNUM":
  11246. case "LARGETRDINNUM":
  11247. case "LARGETRDOUTNUM":
  11248. case "CUR_BUYORDER":
  11249. case "CUR_SELLORDER":
  11250. case "ACTINVOL":
  11251. case "ACTOUTVOL":
  11252. case "BIDORDERVOL":
  11253. case "BIDCANCELVOL":
  11254. case "AVGBIDPX":
  11255. case "OFFERORDERVOL":
  11256. case "OFFERCANCELVOL":
  11257. case "AVGOFFERPX":
  11258. return this.SymbolData.GetStockCacheData({ VariantName:name, Node:node });
  11259. case 'SETCODE':
  11260. return this.SymbolData.SETCODE();
  11261. case 'CODE':
  11262. return this.SymbolData.GetSymbol();
  11263. case 'STKNAME':
  11264. return this.SymbolData.GetName();
  11265. case 'TIME':
  11266. return this.SymbolData.TIME();
  11267. case "TIME2":
  11268. return this.SymbolData.TIME2();
  11269. case 'DATE':
  11270. return this.SymbolData.DATE();
  11271. case "DATETIME":
  11272. return this.SymbolData.DateTime();
  11273. case 'YEAR':
  11274. return this.SymbolData.YEAR();
  11275. case 'MONTH':
  11276. return this.SymbolData.MONTH();
  11277. case 'WEEK':
  11278. case "WEEKDAY":
  11279. return this.SymbolData.WEEK();
  11280. case 'PERIOD':
  11281. return this.SymbolData.PERIOD();
  11282. case 'DRAWNULL':
  11283. case "NULL":
  11284. return this.SymbolData.GetDrawNull();
  11285. case "HOUR":
  11286. return this.SymbolData.HOUR();
  11287. case "MINUTE":
  11288. return this.SymbolData.MINUTE();
  11289. case "TQFLAG":
  11290. return this.SymbolData.Right;
  11291. case "MACHINEDATE":
  11292. {
  11293. var now=new Date();
  11294. return (now.getFullYear()*10000+(now.getMonth()*1)*100+now.getDate())-19000000;
  11295. }
  11296. case "MACHINETIME":
  11297. {
  11298. var now=new Date();
  11299. return now.getHours()*10000+(now.getMinutes()*1)*100+now.getSeconds();
  11300. }
  11301. case "MACHINEWEEK":
  11302. {
  11303. var now=new Date();
  11304. return now.getDay();
  11305. }
  11306. case "WEEKOFYEAR":
  11307. return this.SymbolData.WEEKOFYEAR();
  11308. case "DAYSTOTODAY":
  11309. return this.SymbolData.DAYSTOTODAY();
  11310. default:
  11311. this.ThrowUnexpectedNode(node, '变量'+name+'不存在', name);
  11312. }
  11313. }
  11314. this.ReadCustomVariant=function(name,node)
  11315. {
  11316. return this.SymbolData.GetStockCacheData({ VariantName:name, Node:node });
  11317. }
  11318. //读取变量
  11319. this.ReadVariable=function(name,node)
  11320. {
  11321. if (this.ConstVarTable.has(name))
  11322. {
  11323. let data=this.ConstVarTable.get(name);
  11324. if (data==null) //动态加载,用到再加载
  11325. {
  11326. data=this.ReadSymbolData(name,node);
  11327. this.ConstVarTable.set(name,data);
  11328. }
  11329. return data;
  11330. }
  11331. if (g_JSComplierResource.IsCustomVariant(name)) return this.ReadCustomVariant(name,node); //读取自定义变量
  11332. if (this.VarTable.has(name)) return this.VarTable.get(name);
  11333. if (name.indexOf("COLOR")==0)
  11334. {
  11335. var colorValue=JSComplier.ColorVarToRGB(name);
  11336. if (colorValue) return colorValue;
  11337. }
  11338. this.ThrowUnexpectedNode(node, '变量'+name+'不存在');
  11339. return null;
  11340. }
  11341. this.ReadMemberVariable = function (node)
  11342. {
  11343. var obj = node.Object;
  11344. var member = node.Property;
  11345. let maiObj;
  11346. if (obj.Type == Syntax.BinaryExpression || obj.Type == Syntax.LogicalExpression)
  11347. maiObj = this.VisitBinaryExpression(obj);
  11348. else if (obj.Type == Syntax.CallExpression)
  11349. maiObj = this.VisitCallExpression(obj);
  11350. else
  11351. maiObj = this.GetNodeValue(obj);
  11352. if (!maiObj) return null;
  11353. var value = maiObj[member.Name];
  11354. if (value) return value;
  11355. return null;
  11356. }
  11357. //单数据转成数组 个数和历史数据一致
  11358. this.SingleDataToArrayData = function (value)
  11359. {
  11360. let count = this.SymbolData.Data.Data.length;
  11361. let result = [];
  11362. for (let i = 0; i < count; ++i)
  11363. {
  11364. result[i] = value;
  11365. }
  11366. return result;
  11367. }
  11368. this.RunAST=function()
  11369. {
  11370. //预定义的变量
  11371. for(var i=0; i<this.Arguments.length; ++i)
  11372. {
  11373. var item =this.Arguments[i];
  11374. this.VarTable.set(item.Name,item.Value);
  11375. }
  11376. if (!this.AST) this.ThrowError();
  11377. if (!this.AST.Body) this.ThrowError();
  11378. for(var i=0;i<this.AST.Body.length; ++i)
  11379. {
  11380. var item =this.AST.Body[i];
  11381. this.VisitNode(item);
  11382. //输出变量
  11383. if (item.Type==Syntax.ExpressionStatement && item.Expression)
  11384. {
  11385. if (item.Expression.Type==Syntax.AssignmentExpression && item.Expression.Operator==':' && item.Expression.Left)
  11386. {
  11387. let assignmentItem=item.Expression;
  11388. let varName=assignmentItem.Left.Name;
  11389. let outVar=this.VarTable.get(varName);
  11390. if (this.VarDrawTable.has(varName)) //绘图函数赋值
  11391. {
  11392. let draw=this.VarDrawTable.get(varName);
  11393. this.OutVarTable.push({Name:draw.Name, Draw:draw, Type:1});
  11394. }
  11395. else
  11396. {
  11397. var type=0;
  11398. if (!Array.isArray(outVar))
  11399. {
  11400. if (typeof (outVar) == 'string')
  11401. {
  11402. var floatValue=parseFloat(outVar);
  11403. if (IFrameSplitOperator.IsNumber(floatValue))
  11404. {
  11405. outVar=this.SingleDataToArrayData(floatValue);
  11406. }
  11407. else
  11408. {
  11409. outVar=this.SingleDataToArrayData(outVar);
  11410. type=1001;
  11411. }
  11412. }
  11413. else outVar = this.SingleDataToArrayData(outVar);
  11414. }
  11415. this.OutVarTable.push({Name:varName, Data:outVar,Type:type});
  11416. }
  11417. }
  11418. else if (item.Expression.Type==Syntax.CallExpression)
  11419. {
  11420. let callItem=item.Expression;
  11421. if (this.Draw.IsDrawFunction(callItem.Callee.Name))
  11422. {
  11423. let draw=callItem.Draw;
  11424. draw.Name=callItem.Callee.Name;
  11425. this.OutVarTable.push({Name:draw.Name, Draw:draw, Type:1});
  11426. }
  11427. else if (callItem.Callee.Name==="IFC" && callItem.Draw)
  11428. {
  11429. let draw=callItem.Draw;
  11430. draw.Name=draw.DrawType;
  11431. this.OutVarTable.push({Name:draw.Name, Draw:draw, Type:1});
  11432. }
  11433. else
  11434. {
  11435. let outVar=callItem.Out;
  11436. varName=`__temp_c_${callItem.Callee.Name}_${i}__`;
  11437. var type=0;
  11438. if (!Array.isArray(outVar)) outVar=this.SingleDataToArrayData(outVar);
  11439. this.OutVarTable.push({Name:varName, Data:outVar,Type:type,NoneName:true});
  11440. }
  11441. }
  11442. else if (item.Expression.Type==Syntax.Identifier)
  11443. {
  11444. let varName=item.Expression.Name;
  11445. let outVar=this.ReadVariable(varName,item.Expression);
  11446. var type=0;
  11447. if (!Array.isArray(outVar))
  11448. {
  11449. if (typeof(outVar)=='string') outVar=this.SingleDataToArrayData(parseFloat(outVar));
  11450. else outVar=this.SingleDataToArrayData(outVar);
  11451. }
  11452. varName="__temp_i_"+i+"__";
  11453. this.OutVarTable.push({Name:varName, Data:outVar, Type:type, NoneName:true});
  11454. }
  11455. else if (item.Expression.Type==Syntax.Literal) //常量
  11456. {
  11457. let outVar=item.Expression.Value;
  11458. if (IFrameSplitOperator.IsString(outVar) && outVar.indexOf("$")>0)
  11459. outVar=this.SymbolData.GetOtherSymolCacheData({ Literal:outVar });
  11460. varName="__temp_li_"+i+"__";
  11461. var type=0;
  11462. this.OutVarTable.push({Name:varName, Data:outVar, Type:type, NoneName:true});
  11463. }
  11464. else if (item.Expression.Type==Syntax.BinaryExpression)
  11465. {
  11466. var varName="__temp_b_"+i+"__";
  11467. let outVar=item.Expression.Out;
  11468. var type=0;
  11469. if (!Array.isArray(outVar)) outVar=this.SingleDataToArrayData(outVar);
  11470. this.OutVarTable.push({Name:varName, Data:outVar,Type:type, NoneName:true});
  11471. }
  11472. else if (item.Expression.Type==Syntax.LogicalExpression) //逻辑语句 如 T1 AND T2
  11473. {
  11474. var varName="__temp_l_"+i+"__";
  11475. let outVar=item.Expression.Out;
  11476. var type=0;
  11477. if (!Array.isArray(outVar)) outVar=this.SingleDataToArrayData(outVar);
  11478. this.OutVarTable.push({Name:varName, Data:outVar,Type:type, NoneName:true});
  11479. }
  11480. else if (item.Expression.Type==Syntax.UnaryExpression)
  11481. {
  11482. var varName="__temp_u_"+i+"__";
  11483. var varInfo={ };
  11484. if (this.ReadUnaryExpression(item.Expression, varInfo))
  11485. {
  11486. var type=0;
  11487. this.OutVarTable.push({Name:varName, Data:varInfo.OutVar,Type:type, NoneName:true});
  11488. }
  11489. }
  11490. else if (item.Expression.Type==Syntax.MemberExpression) //MA.MA2
  11491. {
  11492. var outVar=this.ReadMemberVariable(item.Expression);
  11493. if (outVar)
  11494. {
  11495. var type=0;
  11496. var varName="__temp_di_"+i+"__";
  11497. if (!Array.isArray(outVar)) outVar=this.SingleDataToArrayData(outVar);
  11498. this.OutVarTable.push({Name:varName, Data:outVar,Type:type, NoneName:true});
  11499. }
  11500. }
  11501. else if (item.Expression.Type==Syntax.SequenceExpression)
  11502. {
  11503. var varName;
  11504. var draw;
  11505. var color, upColor, downColor, stickType;
  11506. var lineWidth;
  11507. var colorStick=false;
  11508. var pointDot=false;
  11509. var upDownDot=false;
  11510. var circleDot=false;
  11511. var lineStick=false;
  11512. var stick=false;
  11513. var volStick=false;
  11514. var lineArea=false;
  11515. var stepLine=false;
  11516. var isShow = true;
  11517. var isExData = false;
  11518. var isDotLine = false;
  11519. var isOverlayLine = false; //叠加线
  11520. var isSingleLine=false; //独立线段
  11521. var isNoneName=false;
  11522. var isShowTitle=true;
  11523. //显示在位置之上,对于DRAWTEXT和DRAWNUMBER等函数有用,放在语句的最后面(不能与LINETHICK等函数共用),比如:
  11524. //DRAWNUMBER(CLOSE>OPEN,HIGH,CLOSE),DRAWABOVE;
  11525. var isDrawAbove=false;
  11526. //VALIGN0,VALIGN1,VALIGN2 设置文字垂直对齐方式(上中下)
  11527. //ALIGN0,ALIGN1,ALIGN2 设置文字水平对齐方式(左中右)
  11528. var drawAlign=-1, drawVAlign=-1;
  11529. var fontSize=-1;
  11530. var bgConfig=null;
  11531. var vLineConfig=null;
  11532. var xOffset=null, yOffset=null;
  11533. var lineDash=null;
  11534. for(var j=0 ; j<item.Expression.Expression.length; ++j)
  11535. {
  11536. let itemExpression=item.Expression.Expression[j];
  11537. if (itemExpression.Type==Syntax.AssignmentExpression && itemExpression.Operator==':' && itemExpression.Left)
  11538. {
  11539. if (j==0)
  11540. {
  11541. varName = itemExpression.Left.Name;
  11542. let varValue = this.VarTable.get(varName);
  11543. if (this.VarDrawTable.has(varName)) //绘图函数赋值
  11544. {
  11545. draw=this.VarDrawTable.get(varName);
  11546. }
  11547. else if (!Array.isArray(varValue))
  11548. {
  11549. varValue = this.SingleDataToArrayData(varValue);
  11550. this.VarTable.set(varName, varValue); //把常量放到变量表里
  11551. }
  11552. }
  11553. }
  11554. else if (itemExpression.Type==Syntax.Identifier)
  11555. {
  11556. let value=itemExpression.Name;
  11557. if (value==='COLORSTICK') colorStick=true;
  11558. else if (value==='POINTDOT') pointDot=true;
  11559. else if (value=="UPDOWNDOT") upDownDot=true;
  11560. else if (value==='CIRCLEDOT') circleDot=true;
  11561. else if (value == 'DOTLINE') isDotLine = true;
  11562. else if (value==='LINESTICK') lineStick=true;
  11563. else if (value==='STICK') stick=true;
  11564. else if (value==='VOLSTICK') volStick=true;
  11565. else if (value=="LINEAREA") lineArea=true;
  11566. else if (value=="STEPLINE") stepLine=true;
  11567. else if (value==="DRAWABOVE") isDrawAbove=true;
  11568. else if (value==="SINGLELINE") isSingleLine=true;
  11569. else if (value.indexOf('COLOR')==0) color=value;
  11570. else if (value.indexOf("RGBX")==0 && value.length==10) color=value; //RGBX+“RRGGBB”
  11571. else if (value.indexOf('LINETHICK')==0) lineWidth=value;
  11572. else if (value=="ALIGN0") drawAlign=0;
  11573. else if (value=="ALIGN1") drawAlign=1;
  11574. else if (value=="ALIGN2") drawAlign=2;
  11575. else if (value=="VALIGN0") drawVAlign=0;
  11576. else if (value=="VALIGN1") drawVAlign=1;
  11577. else if (value=="VALIGN2") drawVAlign=2;
  11578. else if (value.indexOf('NODRAW') == 0) isShow = false;
  11579. else if (value.indexOf('EXDATA') == 0) isExData = true; //扩展数据, 不显示再图形里面
  11580. else if (value.indexOf('LINEOVERLAY') == 0) isOverlayLine = true;
  11581. else if (value.indexOf("NOTEXT")==0 || value.indexOf("NOTITLE")==0) isShowTitle=false; //标题不显示
  11582. else if (value.indexOf("FONTSIZE")==0)
  11583. {
  11584. var strFontSize=value.replace("FONTSIZE","");
  11585. fontSize=parseInt(strFontSize);
  11586. }
  11587. else
  11588. {
  11589. if (j==0)
  11590. {
  11591. varName=itemExpression.Name;
  11592. let varValue=this.ReadVariable(varName,itemExpression);
  11593. if (!Array.isArray(varValue)) varValue=this.SingleDataToArrayData(varValue);
  11594. varName="__temp_si_"+i+"__";
  11595. isNoneName=true;
  11596. this.VarTable.set(varName,varValue); //放到变量表里
  11597. }
  11598. }
  11599. }
  11600. else if (itemExpression.Type == Syntax.Literal) //常量
  11601. {
  11602. if (j==0)
  11603. {
  11604. let aryValue = this.SingleDataToArrayData(itemExpression.Value);
  11605. varName = itemExpression.Value.toString();
  11606. this.VarTable.set(varName, aryValue); //把常量放到变量表里
  11607. }
  11608. }
  11609. else if (itemExpression.Type==Syntax.CallExpression)
  11610. {
  11611. if (j==0)
  11612. {
  11613. if (this.Draw.IsDrawFunction(itemExpression.Callee.Name))
  11614. {
  11615. draw=itemExpression.Draw;
  11616. draw.Name=itemExpression.Callee.Name;
  11617. }
  11618. else
  11619. {
  11620. let varValue=itemExpression.Out;
  11621. varName=`__temp_sc_${itemExpression.Callee.Name}_${i}__`;
  11622. isNoneName=true;
  11623. this.VarTable.set(varName,varValue);
  11624. }
  11625. }
  11626. else
  11627. {
  11628. if (itemExpression.Callee.Name=="RGB" || itemExpression.Callee.Name=="RGBA")
  11629. {
  11630. color=itemExpression.Out;
  11631. }
  11632. else if (itemExpression.Callee.Name=="UPCOLOR")
  11633. {
  11634. upColor=itemExpression.Out;
  11635. }
  11636. else if (itemExpression.Callee.Name=="DOWNCOLOR")
  11637. {
  11638. downColor=itemExpression.Out;
  11639. }
  11640. else if (itemExpression.Callee.Name=="STICKTYPE")
  11641. {
  11642. stickType=itemExpression.Out;
  11643. }
  11644. else if (itemExpression.Callee.Name=="XMOVE")
  11645. {
  11646. xOffset=itemExpression.Out;
  11647. }
  11648. else if (itemExpression.Callee.Name=="YMOVE")
  11649. {
  11650. yOffset=itemExpression.Out;
  11651. }
  11652. else if (itemExpression.Callee.Name=="LINEDASH")
  11653. {
  11654. if (IFrameSplitOperator.IsNonEmptyArray(itemExpression.Out))
  11655. lineDash=itemExpression.Out.slice();
  11656. }
  11657. else if (itemExpression.Callee.Name=="SOUND")
  11658. {
  11659. var event=this.GetSoundEvent();
  11660. if (event)
  11661. {
  11662. }
  11663. varName=null;
  11664. }
  11665. else if (itemExpression.Callee.Name=="ICON")
  11666. {
  11667. let drawCond=this.VarTable.get(varName);
  11668. if (drawCond)
  11669. {
  11670. draw=this.GetOutIconData(drawCond,itemExpression.Draw);
  11671. if (draw) draw.Name=itemExpression.Callee.Name;
  11672. }
  11673. varName=null;
  11674. }
  11675. else if (itemExpression.Callee.Name=="BACKGROUND")
  11676. {
  11677. bgConfig=itemExpression.Draw;
  11678. varName=null;
  11679. }
  11680. else if (itemExpression.Callee.Name=="CKLINE")
  11681. {
  11682. vLineConfig=itemExpression.Draw;
  11683. varName=null;
  11684. }
  11685. }
  11686. }
  11687. else if (itemExpression.Type==Syntax.BinaryExpression)
  11688. {
  11689. if (j==0)
  11690. {
  11691. varName="__temp_sb_"+i+"__";
  11692. let aryValue=itemExpression.Out;
  11693. isNoneName=true;
  11694. this.VarTable.set(varName,aryValue);
  11695. }
  11696. }
  11697. else if (itemExpression.Type==Syntax.UnaryExpression)
  11698. {
  11699. if (j==0)
  11700. {
  11701. varName="__temp_su_"+i+"__";
  11702. var varInfo={ };
  11703. if (this.ReadUnaryExpression(itemExpression, varInfo))
  11704. {
  11705. isNoneName=true;
  11706. this.VarTable.set(varName,varInfo.OutVar);
  11707. }
  11708. }
  11709. }
  11710. else if (itemExpression.Type==Syntax.MemberExpression) //"MA.MA2"(5,12,29), COLORRED;
  11711. {
  11712. if (j==0)
  11713. {
  11714. var outVar=this.ReadMemberVariable(itemExpression);
  11715. if (outVar)
  11716. {
  11717. if (!Array.isArray(outVar)) varValue=this.SingleDataToArrayData(outVar);
  11718. isNoneName=true;
  11719. varName="__temp_di_"+i+"__";
  11720. this.VarTable.set(varName,outVar); //把常量放到变量表里
  11721. }
  11722. }
  11723. }
  11724. }
  11725. if (pointDot && varName) //圆点
  11726. {
  11727. let outVar=this.VarTable.get(varName);
  11728. let value={Name:varName, Data:outVar, Radius:g_JSChartResource.POINTDOT.Radius, Type:3};
  11729. if (color) value.Color=color;
  11730. if (lineWidth) value.LineWidth = lineWidth;
  11731. this.OutVarTable.push(value);
  11732. }
  11733. else if (circleDot && varName) //圆点
  11734. {
  11735. let outVar=this.VarTable.get(varName);
  11736. let value={Name:varName, Data:outVar, Radius:g_JSChartResource.CIRCLEDOT.Radius, Type:3};
  11737. if (color) value.Color=color;
  11738. if (lineWidth) value.LineWidth = lineWidth;
  11739. this.OutVarTable.push(value);
  11740. }
  11741. else if (upDownDot && varName) //彩色点
  11742. {
  11743. let outVar=this.VarTable.get(varName);
  11744. if (!Array.isArray(outVar)) outVar=this.SingleDataToArrayData(outVar);
  11745. let value={Name:varName, Data:outVar, Radius:g_JSChartResource.CIRCLEDOT.Radius, Type:3, UpDownDot:true };
  11746. if (color) value.Color=color;
  11747. if (lineWidth) value.LineWidth=lineWidth;
  11748. this.OutVarTable.push(value);
  11749. }
  11750. else if (lineStick && varName) //LINESTICK 同时画出柱状线和指标线
  11751. {
  11752. let outVar=this.VarTable.get(varName);
  11753. let value={Name:varName, Data:outVar, Type:4};
  11754. if (color) value.Color=color;
  11755. if (lineWidth) value.LineWidth=lineWidth;
  11756. this.OutVarTable.push(value);
  11757. }
  11758. else if (stick && varName) //STICK 画柱状线
  11759. {
  11760. let outVar=this.VarTable.get(varName);
  11761. let value={Name:varName, Data:outVar, Type:5};
  11762. if (color) value.Color=color;
  11763. if (lineWidth) value.LineWidth=lineWidth;
  11764. this.OutVarTable.push(value);
  11765. }
  11766. else if (volStick && varName) //VOLSTICK 画彩色柱状线
  11767. {
  11768. let outVar=this.VarTable.get(varName);
  11769. let value={Name:varName, Data:outVar, Type:6};
  11770. if (color) value.Color=color;
  11771. if (upColor) value.UpColor=upColor;
  11772. if (downColor) value.DownColor=downColor;
  11773. if (IFrameSplitOperator.IsNumber(stickType)) value.StickType=stickType;
  11774. this.OutVarTable.push(value);
  11775. }
  11776. else if (lineArea && varName) //LINEAREA 面积
  11777. {
  11778. let outVar=this.VarTable.get(varName);
  11779. let value={Name:varName, Data:outVar, Type:9};
  11780. if (color) value.Color=color;
  11781. if (upColor) value.UpColor=upColor;
  11782. if (downColor) value.DownColor=downColor;
  11783. if (lineWidth) value.LineWidth=lineWidth;
  11784. this.OutVarTable.push(value);
  11785. }
  11786. else if (colorStick && varName) //CYW: SUM(VAR4,10)/10000, COLORSTICK; 画上下柱子
  11787. {
  11788. let outVar=this.VarTable.get(varName);
  11789. let value={Name:varName, Data:outVar, Color:color, Type:2};
  11790. if (lineWidth) value.LineWidth=lineWidth;
  11791. if (color) value.Color=color;
  11792. if (upColor) value.UpColor=upColor;
  11793. if (downColor) value.DownColor=downColor;
  11794. this.OutVarTable.push(value);
  11795. }
  11796. else if (varName && color && !draw)
  11797. {
  11798. let outVar=this.VarTable.get(varName);
  11799. let value={Name:varName, Data:outVar, Color:color, Type:0};
  11800. if (lineWidth) value.LineWidth=lineWidth;
  11801. if (isShow == false) value.IsShow = false;
  11802. if (isExData == true) value.IsExData = true;
  11803. if (isDotLine == true) value.IsDotLine = true;
  11804. if (IFrameSplitOperator.IsNonEmptyArray(lineDash)) value.LineDash=lineDash;
  11805. if (isOverlayLine == true) value.IsOverlayLine = true;
  11806. if (isSingleLine == true) value.IsSingleLine = true;
  11807. if (isNoneName==true) value.NoneName=true;
  11808. if (isShowTitle==false) value.IsShowTitle=false;
  11809. if (stepLine==true) value.Type=7;
  11810. this.OutVarTable.push(value);
  11811. }
  11812. else if (draw) //绘图函数
  11813. {
  11814. var outVar = { Name: draw.Name, Draw: draw, Type: 1 };
  11815. if (color) outVar.Color = color;
  11816. if (lineWidth) outVar.LineWidth = lineWidth;
  11817. if (isDrawAbove) outVar.IsDrawAbove=true;
  11818. if (drawAlign>=0) outVar.DrawAlign=drawAlign;
  11819. if (drawVAlign>=0) outVar.DrawVAlign=drawVAlign;
  11820. if (fontSize>0) outVar.DrawFontSize=fontSize;
  11821. if (bgConfig) outVar.Background=bgConfig;
  11822. if (vLineConfig) outVar.VerticalLine=vLineConfig;
  11823. if (IFrameSplitOperator.IsNumber(xOffset)) outVar.XOffset=xOffset;
  11824. if (IFrameSplitOperator.IsNumber(yOffset)) outVar.YOffset=yOffset;
  11825. this.OutVarTable.push(outVar);
  11826. }
  11827. else if (varName)
  11828. {
  11829. let outVar = this.VarTable.get(varName);
  11830. let value = { Name: varName, Data: outVar, Type: 0 };
  11831. if (color) value.Color = color;
  11832. if (lineWidth) value.LineWidth = lineWidth;
  11833. if (isShow == false) value.IsShow = false;
  11834. if (isExData == true) value.IsExData = true;
  11835. if (isDotLine == true) value.IsDotLine = true;
  11836. if (IFrameSplitOperator.IsNonEmptyArray(lineDash)) value.LineDash=lineDash;
  11837. if (isOverlayLine == true) value.IsOverlayLine = true;
  11838. if (isSingleLine == true) value.IsSingleLine = true;
  11839. if (isShowTitle==false) value.IsShowTitle=false;
  11840. if (stepLine==true) value.Type=7;
  11841. this.OutVarTable.push(value);
  11842. }
  11843. }
  11844. }
  11845. if (this.Interrupt && this.Interrupt.Exit)
  11846. {
  11847. JSConsole.Complier.Log('[JSExecute::RunAST] Interrupt', this.Interrupt); //中断退出
  11848. break;
  11849. }
  11850. }
  11851. JSConsole.Complier.Log('[JSExecute::RunAST]', this.VarTable);
  11852. return this.OutVarTable;
  11853. }
  11854. this.ReadUnaryExpression=function(item, varInfo)
  11855. {
  11856. var argument=item.Argument;
  11857. var outVar=null;
  11858. if (argument.Type==Syntax.Literal)
  11859. {
  11860. outVar=argument.Value;
  11861. if (!Array.isArray(outVar)) outVar=this.SingleDataToArrayData(outVar);
  11862. }
  11863. else if (argument.Type==Syntax.Identifier)
  11864. {
  11865. var varName=argument.Name;
  11866. outVar=this.ReadVariable(varName,item.Expression);
  11867. if (!Array.isArray(outVar)) outVar=this.SingleDataToArrayData(outVar);
  11868. }
  11869. else if (argument.Type==Syntax.BinaryExpression)
  11870. {
  11871. outVar=argument.Out;
  11872. if (!Array.isArray(outVar)) outVar=this.SingleDataToArrayData(outVar);
  11873. }
  11874. else if (argument.Type==Syntax.CallExpression)
  11875. {
  11876. var callItem=argument;
  11877. if (this.Draw.IsDrawFunction(callItem.Callee.Name) )
  11878. {
  11879. return false;
  11880. }
  11881. else if (callItem.Callee.Name==="IFC" && callItem.Draw)
  11882. {
  11883. return false;
  11884. }
  11885. else
  11886. {
  11887. outVar=callItem.Out;
  11888. if (!Array.isArray(outVar)) outVar=this.SingleDataToArrayData(outVar);
  11889. }
  11890. }
  11891. else
  11892. {
  11893. return false;
  11894. }
  11895. if (item.Operator=='-')
  11896. {
  11897. if (outVar) outVar=this.Algorithm.Subtract(0,outVar);
  11898. }
  11899. varInfo.OutVar=outVar;
  11900. return true;
  11901. }
  11902. this.GetOutIconData=function(cond, iconDraw)
  11903. {
  11904. if (Array.isArray(cond))
  11905. {
  11906. for(var i=0; i<cond.length && i<iconDraw.DrawData.length; ++i)
  11907. {
  11908. var item=cond[i];
  11909. if (item<=0) iconDraw.DrawData[i]=null;
  11910. }
  11911. return iconDraw;
  11912. }
  11913. if (cond) return iconDraw;
  11914. return null;
  11915. }
  11916. this.GetSoundEvent=function()
  11917. {
  11918. if (!this.GetEventCallback) return null;
  11919. return this.GetEventCallback(JSCHART_EVENT_ID.ON_PLAY_SOUND);
  11920. }
  11921. this.Run=function()
  11922. {
  11923. let data=this.RunAST();//执行脚本
  11924. JSConsole.Complier.Log('[JSComplier.Run] execute finish', data);
  11925. if (this.UpdateUICallback)
  11926. {
  11927. JSConsole.Complier.Log('[JSComplier.Run] invoke UpdateUICallback.');
  11928. if (this.CallbackParam && this.CallbackParam.Job && this.CallbackParam.Job.ID==JS_EXECUTE_JOB_ID.JOB_EXECUTE_INDEX)
  11929. {
  11930. this.UpdateUICallback(data,this.CallbackParam, this.SymbolData);
  11931. }
  11932. else
  11933. {
  11934. if (this.CallbackParam && this.CallbackParam.Self && this.CallbackParam.Self.ClassName==='ScriptIndexConsole') this.CallbackParam.JSExecute=this;
  11935. if (this.IsUsePageData==true) this.CallbackParam.Self.IsUsePageData=true;
  11936. this.UpdateUICallback(data,this.CallbackParam);
  11937. }
  11938. }
  11939. }
  11940. this.VisitNode=function(node)
  11941. {
  11942. switch(node.Type)
  11943. {
  11944. case Syntax.SequenceExpression:
  11945. this.VisitSequenceExpression(node);
  11946. break;
  11947. case Syntax.ExpressionStatement:
  11948. this.VisitNode(node.Expression);
  11949. break;
  11950. case Syntax.AssignmentExpression:
  11951. this.VisitAssignmentExpression(node);
  11952. break;
  11953. case Syntax.BinaryExpression:
  11954. case Syntax.LogicalExpression:
  11955. this.VisitBinaryExpression(node);
  11956. break;
  11957. case Syntax.CallExpression:
  11958. this.VisitCallExpression(node);
  11959. break;
  11960. case Syntax.UnaryExpression:
  11961. this.VisitUnaryExpression(node);
  11962. break;
  11963. }
  11964. }
  11965. this.VisitSequenceExpression=function(node)
  11966. {
  11967. for(let i in node.Expression)
  11968. {
  11969. let item =node.Expression[i];
  11970. this.VisitNode(item);
  11971. }
  11972. }
  11973. this.VisitUnaryExpression=function(node)
  11974. {
  11975. if (node.Operator=='-')
  11976. {
  11977. var tempValue=this.GetNodeValueEx(node.Argument);
  11978. var value=this.Algorithm.Subtract(0,tempValue);
  11979. }
  11980. else
  11981. {
  11982. var value=node.Argument.Value;
  11983. }
  11984. return value;
  11985. }
  11986. this.GetDynamicScriptIndex=function(node, args)
  11987. {
  11988. var dynamicName=node.Callee.Value;
  11989. var aryValue=dynamicName.split(".");
  11990. if (aryValue.length!=2)
  11991. {
  11992. this.ThrowUnexpectedNode(node,`调用指标格式'${dynamicName}'错误`);
  11993. }
  11994. var name=aryValue[0];
  11995. var outName=aryValue[1];
  11996. var period=null;
  11997. var pos=outName.indexOf('#');
  11998. if (pos!=-1)
  11999. {
  12000. period=outName.slice(pos+1); //周期
  12001. outName=outName.slice(0,pos);
  12002. }
  12003. var strValue="";
  12004. for(var i=0; i<args.length; ++i)
  12005. {
  12006. var value=args[i];
  12007. if (strValue.length>0) strValue+=",";
  12008. strValue+=`${value}`;
  12009. }
  12010. var strArgs=`(${strValue})`;
  12011. var key=`${outName}#${strArgs}`;
  12012. if (period) key+=`#${period}`;
  12013. if (!this.VarTable.has(name)) return null;
  12014. var indexData=this.VarTable.get(name);
  12015. var value=indexData[key];
  12016. return value;
  12017. }
  12018. //函数调用
  12019. this.VisitCallExpression=function(node)
  12020. {
  12021. let funcName=node.Callee.Name;
  12022. let args=[];
  12023. for(let i=0; i<node.Arguments.length; ++i)
  12024. {
  12025. let item=node.Arguments[i];
  12026. let value;
  12027. if (funcName==="IFC" && i>=1)
  12028. break; //IFC先处理第1个条件参数
  12029. if (item.Type==Syntax.BinaryExpression || item.Type==Syntax.LogicalExpression)
  12030. value=this.VisitBinaryExpression(item);
  12031. else if (item.Type==Syntax.CallExpression)
  12032. value=this.VisitCallExpression(item);
  12033. else
  12034. value=this.GetNodeValue(item);
  12035. args.push(value);
  12036. }
  12037. if (node.Callee.Type==Syntax.Literal) //指标调用'MA.MA1'(6,12,18)
  12038. {
  12039. node.Out=[];
  12040. node.Draw=null;
  12041. var data=this.GetDynamicScriptIndex(node, args);
  12042. if (data) node.Out=data;
  12043. return node.Out;
  12044. }
  12045. if (funcName==="IFC")
  12046. {
  12047. //IFC(X,A,B)若X不为0则执行A,否则执行B.IFC与IF函数的区别:根据X的值来选择性执行A、B表达式.
  12048. var bResult=this.Algorithm.IFC(args[0]);
  12049. var item=bResult? node.Arguments[1] : node.Arguments[2];
  12050. var value;
  12051. if (item.Type==Syntax.BinaryExpression || item.Type==Syntax.LogicalExpression)
  12052. value=this.VisitBinaryExpression(item);
  12053. else if (item.Type==Syntax.CallExpression)
  12054. value=this.VisitCallExpression(item);
  12055. else
  12056. value=this.GetNodeValue(item);
  12057. node.Out=value;
  12058. if (item.Draw) node.Draw=item.Draw;
  12059. return node.Out;
  12060. }
  12061. //if (JS_EXECUTE_DEBUG_LOG) JSConsole.Complier.Log('[JSExecute::VisitCallExpression]' , funcName, '(', args.toString() ,')');
  12062. if (g_JSComplierResource.IsCustomFunction(funcName)) //自定义函数
  12063. {
  12064. var data=this.Algorithm.CallCustomFunction(funcName, args, this.SymbolData, node);
  12065. node.Out=[];
  12066. node.Draw=null;
  12067. if (data)
  12068. {
  12069. if (data.Out) node.Out=data.Out;
  12070. if (data.Draw) node.Draw=data.Draw;
  12071. }
  12072. return node.Out;
  12073. }
  12074. if (g_JSComplierResource.IsCustomDataFunction(funcName))
  12075. {
  12076. var functionInfo=g_JSComplierResource.CustomDataFunction.Data.get(funcName);
  12077. node.Out=this.SymbolData.GetStockCacheData( {FunctionName:funcName, Args:args, ArgCount:functionInfo.ArgCount, Node:node } );
  12078. node.Draw=null;
  12079. return node.Out;
  12080. }
  12081. switch(funcName)
  12082. {
  12083. case 'DYNAINFO': //行情最新数据
  12084. node.Out=this.SymbolData.GetLatestCacheData(args[0]);
  12085. break;
  12086. case 'STICKLINE':
  12087. node.Draw=this.Draw.STICKLINE(args[0],args[1],args[2],args[3],args[4]);
  12088. node.Out=[];
  12089. break;
  12090. case 'DRAWTEXT':
  12091. node.Draw=this.Draw.DRAWTEXT(args[0],args[1],args[2]);
  12092. node.Out=[];
  12093. break;
  12094. case 'SUPERDRAWTEXT':
  12095. node.Draw = this.Draw.SUPERDRAWTEXT(args[0], args[1], args[2], args[3], args[4]);
  12096. node.Out = [];
  12097. break;
  12098. case 'DRAWTEXT_FIX':
  12099. node.Draw=this.Draw.DRAWTEXT_FIX(args[0],args[1],args[2],args[3],args[4]);
  12100. node.Out=[];
  12101. break;
  12102. case 'DRAWICON':
  12103. node.Draw = this.Draw.DRAWICON(args[0], args[1], args[2], args[3]);
  12104. node.Out = [];
  12105. break;
  12106. case "ICON":
  12107. node.Draw=this.Draw.ICON(args[0],args[1]);
  12108. node.Out=[];
  12109. break;
  12110. case "BACKGROUND":
  12111. node.Draw=this.Draw.BACKGROUND(args[0],args[1],args[2],args[3],args[4],args[5]);
  12112. node.Out=[];
  12113. break;
  12114. case "CKLINE":
  12115. node.Draw=this.Draw.CKLINE(args[0],args[1],args[2],args[3],args[4]);
  12116. node.Out=[];
  12117. break;
  12118. case 'DRAWLINE':
  12119. node.Draw=this.Draw.DRAWLINE(args[0],args[1],args[2],args[3],args[4]);
  12120. node.Out=node.Draw.DrawData;
  12121. break;
  12122. case 'DRAWBAND':
  12123. node.Draw=this.Draw.DRAWBAND(args[0],args[1],args[2],args[3]);
  12124. node.Out=[];
  12125. break;
  12126. case 'DRAWKLINE':
  12127. case "DRAWKLINE1":
  12128. node.Draw = this.Draw.DRAWKLINE(args[0], args[1], args[2], args[3]);
  12129. node.Out = [];
  12130. break;
  12131. case 'DRAWKLINE_IF':
  12132. node.Draw = this.Draw.DRAWKLINE_IF(args[0], args[1], args[2], args[3], args[4]);
  12133. node.Out = [];
  12134. break;
  12135. case "DRAWCOLORKLINE":
  12136. node.Draw=this.Draw.DRAWCOLORKLINE(args[0],args[1],args[2]);
  12137. node.Out=[];
  12138. break;
  12139. case 'PLOYLINE':
  12140. case 'POLYLINE':
  12141. node.Draw = this.Draw.POLYLINE(args[0], args[1]);
  12142. node.Out = node.Draw.DrawData;
  12143. break;
  12144. case 'DRAWNUMBER':
  12145. node.Draw = this.Draw.DRAWNUMBER(args[0], args[1], args[2], args[3]);
  12146. node.Out = node.Draw.DrawData.Value;
  12147. break;
  12148. case 'RGB':
  12149. node.Out = this.Draw.RGB(args[0], args[1], args[2]);
  12150. break;
  12151. case 'RGBA':
  12152. node.Out = this.Draw.RGBA(args[0], args[1], args[2],args[3]);
  12153. break;
  12154. case "UPCOLOR":
  12155. node.Out=this.Draw.UPCOLOR(args[0]);
  12156. break;
  12157. case "DOWNCOLOR":
  12158. node.Out=this.Draw.DOWNCOLOR(args[0]);
  12159. break;
  12160. case "STICKTYPE":
  12161. node.Out=this.Draw.STICKTYPE(args[0]);
  12162. break;
  12163. case "XMOVE":
  12164. node.Out=this.Draw.XMOVE(args[0]);
  12165. break;
  12166. case "YMOVE":
  12167. node.Out=this.Draw.YMOVE(args[0]);
  12168. break;
  12169. case "LINEDASH":
  12170. node.Out=this.Draw.LINEDASH(args);
  12171. break;
  12172. case 'DRAWRECTREL':
  12173. node.Draw = this.Draw.DRAWRECTREL(args[0], args[1], args[2], args[3], args[4]);
  12174. node.Out = [];
  12175. break;
  12176. case "DRAWTEXTREL":
  12177. node.Draw=this.Draw.DRAWTEXTREL(args[0],args[1],args[2]);
  12178. node.Out=[];
  12179. break;
  12180. case "DRAWTEXTABS":
  12181. node.Draw=this.Draw.DRAWTEXTABS(args[0],args[1],args[2]);
  12182. node.Out=[];
  12183. break;
  12184. case 'DRAWGBK':
  12185. node.Draw=this.Draw.DRAWGBK(args[0],args[1],args[2],args[3]);
  12186. node.Out=[];
  12187. break;
  12188. case 'DRAWGBK2':
  12189. node.Draw=this.Draw.DRAWGBK2(args[0],args[1],args[2],args[3]);
  12190. node.Out=[];
  12191. break;
  12192. case "DRAWGBK_DIV":
  12193. node.Draw=this.Draw.DRAWGBK_DIV(args[0],args[1],args[2],args[3],args[4]);
  12194. node.Out=[];
  12195. break;
  12196. case 'CODELIKE':
  12197. node.Out=this.SymbolData.CODELIKE(args[0]);
  12198. break;
  12199. case 'NAMELIKE':
  12200. case "NAMEINCLUDE":
  12201. node.Out = this.SymbolData.NAMELIKE(args[1]);
  12202. break;
  12203. case 'REFDATE':
  12204. node.Out = this.SymbolData.REFDATE(args[0], args[1]);
  12205. break;
  12206. case 'FINANCE':
  12207. node.Out=this.SymbolData.GetStockCacheData( {FunctionName:funcName, Args:args, ArgCount:1, Node:node } );
  12208. break;
  12209. case "FINVALUE":
  12210. node.Out=this.SymbolData.GetStockCacheData( {FunctionName:funcName, Args:args, ArgCount:1, Node:node } );
  12211. break;
  12212. case "FINONE":
  12213. node.Out=this.SymbolData.GetStockCacheData( {FunctionName:funcName, Args:args, ArgCount:3, Node:node } );
  12214. break;
  12215. case "GPJYVALUE":
  12216. case "SCJYVALUE":
  12217. case "BKJYVALUE":
  12218. node.Out=this.SymbolData.GetStockCacheData( {FunctionName:funcName, Args:args, ArgCount:3, Node:node } );
  12219. break;
  12220. case "GPJYONE":
  12221. case "SCJYONE":
  12222. case "BKJYONE":
  12223. node.Out=this.SymbolData.GetStockCacheData( {FunctionName:funcName, Args:args, ArgCount:4, Node:node } );
  12224. break;
  12225. case "MARGIN":
  12226. node.Out = this.SymbolData.GetMarginCacheData(args[0], node);
  12227. break;
  12228. case "NEWS":
  12229. node.Out = this.SymbolData.GetNewsAnalysisCacheData(args[0], node);
  12230. break;
  12231. case 'UPCOUNT':
  12232. case 'DOWNCOUNT':
  12233. node.Out = this.SymbolData.GetIndexIncreaseCacheData(funcName, args[0], node);
  12234. break;
  12235. case 'LOADAPIDATA':
  12236. node.Out = this.SymbolData.GetCustomApiData(args);
  12237. break;
  12238. case "STKINDI":
  12239. case "CALCSTOCKINDEX":
  12240. node.Out=this.SymbolData.GetScriptIndexOutData(args,node,funcName);
  12241. break;
  12242. case 'CLOSE':
  12243. case 'C':
  12244. case 'VOL':
  12245. case 'V':
  12246. case 'OPEN':
  12247. case 'O':
  12248. case 'HIGH':
  12249. case 'H':
  12250. case 'LOW':
  12251. case 'L':
  12252. case 'AMOUNT':
  12253. case 'AMO':
  12254. node.Out=this.SymbolData.GetOtherSymolCacheData( {FunctionName:funcName, Args:args} );
  12255. break;
  12256. case "INBLOCK":
  12257. node.Out=this.SymbolData.IsInBlock(args[0],node);
  12258. break;
  12259. case "SYSPARAM":
  12260. node.Out=this.SymbolData.SysParam(args[0], this);
  12261. break;
  12262. case "TESTSKIP":
  12263. var bExit=this.Algorithm.TESTSKIP(args[0],node);
  12264. node.Out=null;
  12265. if (bExit)
  12266. {
  12267. this.Interrupt.Exit=true;
  12268. if (node && node.Marker)
  12269. {
  12270. var marker=node.Marker;
  12271. this.Interrupt.Line=marker.Line;
  12272. this.Interrupt.Index=marker.Index;
  12273. this.Interrupt.Column=marker.Column;
  12274. }
  12275. }
  12276. break;
  12277. default:
  12278. node.Out=this.Algorithm.CallFunction(funcName, args,node);
  12279. break;
  12280. }
  12281. return node.Out;
  12282. }
  12283. //赋值
  12284. this.VisitAssignmentExpression=function(node)
  12285. {
  12286. let left=node.Left;
  12287. if (left.Type!=Syntax.Identifier) this.ThrowUnexpectedNode(node);
  12288. let varName=left.Name;
  12289. let right=node.Right;
  12290. let value=null,drawValue=null;
  12291. if (right.Type==Syntax.BinaryExpression || right.Type==Syntax.LogicalExpression)
  12292. value=this.VisitBinaryExpression(right);
  12293. else if (right.Type==Syntax.CallExpression)
  12294. {
  12295. value=this.VisitCallExpression(right);
  12296. if (right.Draw) drawValue=right.Draw;
  12297. }
  12298. else if (right.Type==Syntax.Literal)
  12299. {
  12300. value=right.Value;
  12301. if (IFrameSplitOperator.IsString(value) && right.Value.indexOf("$")>0)
  12302. value=this.SymbolData.GetOtherSymolCacheData( {Literal:value} );
  12303. }
  12304. else if (right.Type==Syntax.Identifier) //右值是变量
  12305. value=this.ReadVariable(right.Name,right);
  12306. else if (right.Type == Syntax.MemberExpression)
  12307. value = this.ReadMemberVariable(right);
  12308. else if (right.Type==Syntax.UnaryExpression)
  12309. value=this.VisitUnaryExpression(right);
  12310. if (JS_EXECUTE_DEBUG_LOG) JSConsole.Complier.Log('[JSExecute::VisitAssignmentExpression]' , varName, ' = ',value);
  12311. if (drawValue) this.VarDrawTable.set(varName, drawValue);
  12312. this.VarTable.set(varName,value);
  12313. }
  12314. //逻辑运算
  12315. this.VisitBinaryExpression=function(node)
  12316. {
  12317. let stack=[];
  12318. stack.push(node);
  12319. let temp=null;
  12320. while(stack.length!=0)
  12321. {
  12322. temp=stack[stack.length-1];
  12323. if (temp.Left && node!=temp.Left && node!=temp.Right)
  12324. {
  12325. stack.push(temp.Left);
  12326. }
  12327. else if (temp.Right && node!=temp.Right)
  12328. {
  12329. stack.push(temp.Right);
  12330. }
  12331. else
  12332. {
  12333. let value=stack.pop();
  12334. if (value.Type==Syntax.BinaryExpression) //只遍历操作符就可以
  12335. {
  12336. let leftValue=this.GetNodeValue(value.Left);
  12337. let rightValue=this.GetNodeValue(value.Right);
  12338. if (JS_EXECUTE_DEBUG_LOG) JSConsole.Complier.Log('[JSExecute::VisitBinaryExpression] BinaryExpression',value , leftValue, rightValue);
  12339. value.Out=null; //保存中间值
  12340. switch(value.Operator)
  12341. {
  12342. case '-':
  12343. value.Out=this.Algorithm.Subtract(leftValue,rightValue);
  12344. break;
  12345. case '*':
  12346. value.Out=this.Algorithm.Multiply(leftValue,rightValue);
  12347. break;
  12348. case '/':
  12349. value.Out=this.Algorithm.Divide(leftValue,rightValue)
  12350. break;
  12351. case '+':
  12352. value.Out=this.Algorithm.Add(leftValue,rightValue);
  12353. break;
  12354. case '>':
  12355. value.Out=this.Algorithm.GT(leftValue,rightValue);
  12356. break;
  12357. case '>=':
  12358. value.Out=this.Algorithm.GTE(leftValue,rightValue);
  12359. break;
  12360. case '<':
  12361. value.Out=this.Algorithm.LT(leftValue,rightValue);
  12362. break;
  12363. case '<=':
  12364. value.Out=this.Algorithm.LTE(leftValue,rightValue);
  12365. break;
  12366. case '==':
  12367. case '=':
  12368. value.Out=this.Algorithm.EQ(leftValue,rightValue);
  12369. break;
  12370. case '!=':
  12371. case '<>':
  12372. value.Out = this.Algorithm.NEQ(leftValue, rightValue);
  12373. break;
  12374. }
  12375. if (JS_EXECUTE_DEBUG_LOG) JSConsole.Complier.Log('[JSExecute::VisitBinaryExpression] BinaryExpression',value);
  12376. }
  12377. else if (value.Type==Syntax.LogicalExpression)
  12378. {
  12379. let leftValue=this.GetNodeValue(value.Left);
  12380. let rightValue=this.GetNodeValue(value.Right);
  12381. if (JS_EXECUTE_DEBUG_LOG) JSConsole.Complier.Log('[JSExecute::VisitBinaryExpression] LogicalExpression',value , leftValue, rightValue);
  12382. value.Out=null; //保存中间值
  12383. switch(value.Operator)
  12384. {
  12385. case '&&':
  12386. case 'AND':
  12387. value.Out=this.Algorithm.And(leftValue,rightValue);
  12388. break;
  12389. case '||':
  12390. case 'OR':
  12391. value.Out=this.Algorithm.Or(leftValue,rightValue);
  12392. break;
  12393. }
  12394. if (JS_EXECUTE_DEBUG_LOG) JSConsole.Complier.Log('[JSExecute::VisitBinaryExpression] LogicalExpression',value);
  12395. }
  12396. node=temp;
  12397. }
  12398. }
  12399. return node.Out;
  12400. }
  12401. //获取节点值,BinaryExpression,LogicalExpression会重新计算
  12402. this.GetNodeValueEx=function(item)
  12403. {
  12404. var value=null;
  12405. if (item.Type==Syntax.BinaryExpression || item.Type==Syntax.LogicalExpression)
  12406. value=this.VisitBinaryExpression(item);
  12407. else if (item.Type==Syntax.CallExpression)
  12408. value=this.VisitCallExpression(item);
  12409. else
  12410. value=this.GetNodeValue(item);
  12411. return value;
  12412. }
  12413. this.GetNodeValue=function(node)
  12414. {
  12415. switch(node.Type)
  12416. {
  12417. case Syntax.Literal: //数字
  12418. return node.Value;
  12419. case Syntax.UnaryExpression:
  12420. var value=this.VisitUnaryExpression(node);
  12421. return value;
  12422. case Syntax.Identifier:
  12423. var value=this.ReadVariable(node.Name,node);
  12424. return value;
  12425. case Syntax.BinaryExpression:
  12426. case Syntax.LogicalExpression:
  12427. return node.Out;
  12428. case Syntax.CallExpression:
  12429. return this.VisitCallExpression(node);
  12430. case Syntax.MemberExpression:
  12431. return this.ReadMemberVariable(node);
  12432. default:
  12433. this.ThrowUnexpectedNode(node);
  12434. }
  12435. }
  12436. this.ThrowUnexpectedNode=function(node,message)
  12437. {
  12438. let marker=node.Marker;
  12439. let msg=message || "执行异常";
  12440. return this.ErrorHandler.ThrowError(marker.Index,marker.Line,marker.Column,msg);
  12441. }
  12442. this.ThrowError=function()
  12443. {
  12444. }
  12445. }
  12446. //对外导出类
  12447. function JSComplier()
  12448. {
  12449. }
  12450. //词法分析
  12451. JSComplier.Tokenize=function(code)
  12452. {
  12453. JSConsole.Complier.Log('[JSComplier.Tokenize]', code);
  12454. let tokenizer=new Tokenizer(code);
  12455. let tokens=[];
  12456. try
  12457. {
  12458. while(true)
  12459. {
  12460. let token=tokenizer.GetNextToken();
  12461. if (!token) break;
  12462. tokens.push(token);
  12463. }
  12464. }
  12465. catch(e)
  12466. {
  12467. }
  12468. return tokens;
  12469. }
  12470. //语法解析 生成抽象语法树(Abstract Syntax Tree)
  12471. JSComplier.Parse=function(code)
  12472. {
  12473. JSConsole.Complier.Log('[JSComplier.Parse]',code);
  12474. let parser=new JSParser(code);
  12475. parser.Initialize();
  12476. let program=parser.ParseScript();
  12477. let ast=program;
  12478. return ast;
  12479. }
  12480. //颜色转rgb
  12481. JSComplier.ColorVarToRGB=function(colorName)
  12482. {
  12483. let COLOR_MAP=new Map(
  12484. [
  12485. ['COLORBLACK','rgb(0,0,0)'],
  12486. ['COLORBLUE','rgb(18,95,216)'],
  12487. ['COLORGREEN','rgb(25,158,0)'],
  12488. ['COLORCYAN','rgb(0,255,198)'],
  12489. ['COLORRED','rgb(238,21,21)'],
  12490. ['COLORMAGENTA','rgb(255,0,222)'],
  12491. ['COLORBROWN','rgb(149,94,15)'],
  12492. ['COLORLIGRAY','rgb(218,218,218)'], //画淡灰色
  12493. ['COLORGRAY','rgb(133,133,133)'], //画深灰色
  12494. ['COLORLIBLUE','rgb(94,204,255)'], //淡蓝色
  12495. ['COLORLIGREEN','rgb(183,255,190)'], //淡绿色
  12496. ['COLORLICYAN','rgb(154,255,242)'], //淡青色
  12497. ['COLORLIRED','rgb(255,172,172)'], //淡红色
  12498. ['COLORLIMAGENTA','rgb(255,145,241)'], //淡洋红色
  12499. ['COLORWHITE','rgb(255,255,255)'], //白色
  12500. ['COLORYELLOW','rgb(255,198,0)']
  12501. ]);
  12502. if (COLOR_MAP.has(colorName)) return COLOR_MAP.get(colorName);
  12503. //COLOR 自定义色
  12504. //格式为COLOR+“BBGGRR”:BB、GG、RR表示蓝色、绿色和红色的分量,每种颜色的取值范围是00-FF,采用了16进制。
  12505. //例如:MA5:MA(CLOSE,5),COLOR00FFFF表示纯红色与纯绿色的混合色:COLOR808000表示淡蓝色和淡绿色的混合色。
  12506. if (colorName.indexOf('COLOR')==0)
  12507. {
  12508. var strColor=colorName.substr(5);
  12509. if (strColor.length!=6) return null;
  12510. var value=strColor.substr(0,2);
  12511. var b=parseInt(value,16);
  12512. value=strColor.substr(2,2);
  12513. var g=parseInt(value,16);
  12514. value=strColor.substr(4,2);
  12515. var r=parseInt(value,16);
  12516. return `rgb(${r},${g},${b})`;
  12517. }
  12518. //格式为RGBX+“RRGGBB”:RR、GG、BB表示红色、绿色和的蓝色分量,每种颜色的取值范围是00-FF,采用了16进制。
  12519. //例如:MA5:MA(CLOSE,5),RGBXFFFF00表示纯红色与纯绿色的混合色:RGBX008080表示淡蓝色和淡绿色的混合色。
  12520. if (colorName.indexOf("RGBX")==0)
  12521. {
  12522. var strColor=colorName.substr(4);
  12523. if (strColor.length!=6) return null;
  12524. var value=strColor.substr(0,2);
  12525. var r=parseInt(value,16);
  12526. value=strColor.substr(2,2);
  12527. var g=parseInt(value,16);
  12528. value=strColor.substr(4,2);
  12529. var b=parseInt(value,16);
  12530. return `rgb(${r},${g},${b})`;
  12531. }
  12532. return null;
  12533. }
  12534. /*
  12535. 执行
  12536. option.Symbol=股票代码
  12537. option.Name=股票名称
  12538. option.Data=这个股票的ChartData
  12539. option.Right=复权
  12540. option.MaxRequestDataCount=请求数据的最大个数
  12541. */
  12542. function timeout(ms) {
  12543. return new Promise((resolve) => {
  12544. setTimeout(resolve, ms);
  12545. });
  12546. }
  12547. JSComplier.Execute=function(code,option,errorCallback)
  12548. {
  12549. //异步调用
  12550. var asyncExecute= function()
  12551. {
  12552. try
  12553. {
  12554. JSConsole.Complier.Log('[JSComplier.Execute] code ',code);
  12555. JSConsole.Complier.Log('[JSComplier.Execute] parser .....');
  12556. let parser=new JSParser(code);
  12557. parser.Initialize();
  12558. let program=parser.ParseScript();
  12559. let ast=program;
  12560. JSConsole.Complier.Log('[JSComplier.Execute] parser finish.', ast);
  12561. JSConsole.Complier.Log('[JSComplier.Execute] execute .....');
  12562. let execute=new JSExecute(ast,option);
  12563. execute.JobList=parser.Node.GetDataJobList();
  12564. execute.JobList.push({ID:JS_EXECUTE_JOB_ID.JOB_RUN_SCRIPT});
  12565. let result=execute.Execute();
  12566. }catch(error)
  12567. {
  12568. JSConsole.Complier.Log(error);
  12569. if (errorCallback) errorCallback(error);
  12570. }
  12571. }
  12572. asyncExecute();
  12573. JSConsole.Complier.Log('[JSComplier.Execute] async execute.');
  12574. }
  12575. JSComplier.SetDomain = function (domain, cacheDomain)
  12576. {
  12577. if (domain) g_JSComplierResource.Domain = domain;
  12578. if (cacheDomain) g_JSComplierResource.CacheDomain = cacheDomain;
  12579. }
  12580. JSComplier.AddFunction=function(obj) //添加函数 { Name:函数名, Description:描述信息, IsDownload:是否需要下载数据, Invoke:函数执行(可选) }
  12581. {
  12582. if (!obj || !obj.Name) return;
  12583. var ID=obj.Name.toUpperCase();
  12584. g_JSComplierResource.CustomFunction.Data.set(ID, obj);
  12585. }
  12586. JSComplier.AddVariant=function(obj) //{ Name:变量名, Description:描述信息 }
  12587. {
  12588. if (!obj || !obj.Name) return;
  12589. var ID=obj.Name.toUpperCase();
  12590. g_JSComplierResource.CustomVariant.Data.set(ID, obj);
  12591. }
  12592. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  12593. //
  12594. //数据下载
  12595. function DownloadFinanceData(obj)
  12596. {
  12597. this.Url=obj.Url;
  12598. this.RealtimeUrl=obj.RealtimeUrl;
  12599. this.Job=obj.Job;
  12600. this.Symbol=obj.Symbol;
  12601. this.Args=obj.Args;
  12602. this.DataKey=obj.DataKey;
  12603. this.RecvCallback=obj.Callback;
  12604. this.ErrorCallback=obj.ErrorCallback;
  12605. this.Download=function()
  12606. {
  12607. var id=this.Args[0];
  12608. switch(id)
  12609. {
  12610. case 1: //FINANCE(1) 总股本(随时间可能有变化) 股
  12611. case 7: //FINANCE(7) 流通股本(随时间可能有变化) 股
  12612. case "EXCHANGE": //换手率
  12613. this.DownloadHistoryData(id);
  12614. break;
  12615. case 9: //FINANCE(9) 资产负债率
  12616. case 18: //FINANCE(18) 每股公积金
  12617. case 30: //FINANCE(30) 净利润
  12618. case 32: //FINANCE(32) 每股未分配利润
  12619. case 33: //FINANCE(33) 每股收益(折算为全年收益),对于沪深品种有效
  12620. case 34: //FINANCE(34) 每股净资产
  12621. case 38: //FINANCE(38) 每股收益(最近一期季报)
  12622. case 40: //FINANCE(40) 流通市值
  12623. case 41: //FINANCE(41) 总市值
  12624. case 42: //FINANCE(42) 上市的天数
  12625. case 43: //FINANCE(43) 利润同比
  12626. case "CAPITAL":
  12627. case "TOTALCAPITAL":
  12628. //定制
  12629. case 100: //股东人数
  12630. this.DownloadRealtimeData(id);
  12631. break;
  12632. default:
  12633. this.DownloadRealtimeData(id);
  12634. break;
  12635. }
  12636. }
  12637. //最新一期数据
  12638. this.DownloadRealtimeData=function(id)
  12639. {
  12640. var self=this;
  12641. var fieldList=this.GetFieldList();
  12642. if (!fieldList)
  12643. {
  12644. if (this.Job.FunctionName2) message=`${this.Job.FunctionName2} can't support.`;
  12645. else if (this.Job.FunctionName) message=`${this.Job.FunctionName}(${this.Args[0]}) can't support.`;
  12646. else message=`${this.Args[0]} can't support.`;
  12647. this.ErrorCallback(message);
  12648. self.RecvCallback(null, self.Job, self.DataKey);
  12649. return;
  12650. }
  12651. //请求数据
  12652. JSNetwork.HttpRequest({
  12653. url: this.RealtimeUrl,
  12654. data:
  12655. {
  12656. "field": fieldList,
  12657. "symbol": [this.Symbol],
  12658. "condition":[ ] ,
  12659. "start": 0,
  12660. "end": 10
  12661. },
  12662. method: 'POST',
  12663. dataType: "json",
  12664. async:true,
  12665. success: function (recvData)
  12666. {
  12667. var data=self.RealtimeDataToHQChartData(recvData.data);
  12668. self.RecvCallback(data, self.Job, self.DataKey);
  12669. }
  12670. });
  12671. }
  12672. //历史数据
  12673. this.DownloadHistoryData=function(id)
  12674. {
  12675. var self=this;
  12676. var fieldList=this.GetFieldList();
  12677. if (!fieldList)
  12678. {
  12679. message=`${this.Job.FunctionName}(${this.Args[0]}) can't support.`;
  12680. this.ErrorCallback(message);
  12681. self.RecvCallback(null, self.Job, self.DataKey);
  12682. return;
  12683. }
  12684. //请求数据
  12685. JSNetwork.HttpRequest({
  12686. url: this.Url,
  12687. data:
  12688. {
  12689. "field": fieldList,
  12690. "symbol": [this.Symbol],
  12691. "condition":[ ] ,
  12692. "start": 0,
  12693. "end": 200
  12694. },
  12695. method: 'POST',
  12696. dataType: "json",
  12697. async:true,
  12698. success: function (recvData)
  12699. {
  12700. var data=self.ToHQChartData(recvData.data);
  12701. if (data) //排序
  12702. data.sort(function (a, b) { return (a.Date - b.Date) });
  12703. self.RecvCallback(data, self.Job, self.DataKey);
  12704. }
  12705. });
  12706. }
  12707. this.GetFieldList=function()
  12708. {
  12709. var id=this.Args[0];
  12710. switch(id)
  12711. {
  12712. case 1:
  12713. return ["capital.total", "capital.date"];
  12714. case 7:
  12715. return ["capital.a", "capital.date"];
  12716. case "EXCHANGE":
  12717. return ["capital.a", "capital.date"];
  12718. case 9:
  12719. return ["finance.peruprofit","symbol","date"];
  12720. case 18:
  12721. return ["finance.percreserve","symbol","date"];
  12722. case 30:
  12723. return ["finance.nprofit","symbol","date"];
  12724. case 32:
  12725. return ["finance.peruprofit","symbol","date"];
  12726. case 33:
  12727. return ["finance.persearning","symbol","date"];
  12728. case 34:
  12729. return ["finance.pernetasset","symbol","date"];
  12730. case 38:
  12731. return ["finance.persearning","symbol","date"];
  12732. case 40:
  12733. return ["capital.a", "capital.date","symbol","date", "price"];
  12734. case 41:
  12735. return ["capital.total", "capital.date","symbol","date","price"];
  12736. case "CAPITAL":
  12737. return ["capital.a", "capital.date","symbol","date"];
  12738. case "TOTALCAPITAL":
  12739. return ["capital.total", "capital.date","symbol","date"];
  12740. case 42:
  12741. return ["company.releasedate","symbol","date"];
  12742. case 43:
  12743. return ["dividendyield","symbol","date"];
  12744. case 100:
  12745. return ["shareholder","symbol","date"]
  12746. default:
  12747. return null;
  12748. }
  12749. }
  12750. //最新报告期数据
  12751. this.RealtimeDataToHQChartData=function(recvData,id)
  12752. {
  12753. if (!recvData.stock || recvData.stock.length!=1) return null;
  12754. var stock=recvData.stock[0];
  12755. var id=this.Args[0];
  12756. var date=stock.date;
  12757. switch(id)
  12758. {
  12759. case 9:
  12760. if (!stock.finance) return null;
  12761. return { Date:date, Value:stock.finance.peruprofit };
  12762. case 18:
  12763. if (!stock.finance) return null;
  12764. return { Date:date, Value:stock.finance.percreserve };
  12765. case 30:
  12766. if (!stock.finance) return null;
  12767. return { Date:date, Value:stock.finance.nprofit };
  12768. case 32:
  12769. if (!stock.finance) return null;
  12770. return { Date:date, Value:stock.finance.peruprofit };
  12771. case 33:
  12772. if (!stock.finance) return null;
  12773. return { Date:date, Value:stock.finance.persearning };
  12774. case 34:
  12775. if (!stock.finance) return null;
  12776. return { Date:date, Value:stock.finance.pernetasset };
  12777. case 38:
  12778. if (!stock.finance) return null;
  12779. return { Date:date, Value:stock.finance.persearning };
  12780. case 40: //FINANCE(40) 流通市值
  12781. if (!stock.capital) return null;
  12782. return { Date:date, Value:stock.capital.a*stock.price }; //流通股*最新价格
  12783. case 41: //FINANCE(41) 总市值
  12784. if (!stock.capital) return null;
  12785. return { Date:date, Value:stock.capital.total*stock.price }; //总股本*最新价格
  12786. case 42: //FINANCE(42) 上市的天数
  12787. if (!stock.company) return null;
  12788. {
  12789. var releaseDate=stock.company.releasedate;
  12790. var year=parseInt(releaseDate/10000);
  12791. var month=parseInt((releaseDate%10000)/100);
  12792. var day=releaseDate%100;
  12793. var firstDate=new Date(year, month-1, day);
  12794. var nowDate=new Date();
  12795. var days=parseInt((nowDate.getTime()-firstDate.getTime())/(1000 * 60 * 60 * 24));
  12796. return { Date:date, Value:days+1 };
  12797. }
  12798. case 43:
  12799. if (!stock.dividendyield) return null;
  12800. return { Date:date, Value:stock.dividendyield.quarter4 };
  12801. case 100:
  12802. if (!stock.shareholder) return null;
  12803. return { Date:date, Value:stock.shareholder.count };
  12804. case "CAPITAL":
  12805. if (!stock.capital) return null;
  12806. return { Date:date, Value:stock.capital.a/100 }; //当前流通股本 手
  12807. case "TOTALCAPITAL":
  12808. if (!stock.capital) return null;
  12809. return { Date:date, Value:stock.capital.total/100 }; //当前流通股本 手
  12810. }
  12811. }
  12812. //历史数据转
  12813. this.ToHQChartData=function(recvData)
  12814. {
  12815. if (!recvData.stock || recvData.stock.length!=1) return null;
  12816. var aryData=[];
  12817. var setDate=new Set(); //有重复数据 去掉
  12818. var stock=recvData.stock[0];
  12819. var id=this.Args[0];
  12820. for(var i in stock.stockday)
  12821. {
  12822. var item=stock.stockday[i];
  12823. var hqchartItem=this.ToHQChartItemData(item,id);
  12824. if (hqchartItem && !setDate.has(hqchartItem.Date))
  12825. {
  12826. aryData.push(hqchartItem);
  12827. setDate.add(hqchartItem.Date);
  12828. }
  12829. }
  12830. return aryData;
  12831. }
  12832. this.ToHQChartItemData=function(item, id)
  12833. {
  12834. if (!item) return null;
  12835. var date=item.date;
  12836. switch(id)
  12837. {
  12838. case 1:
  12839. if (!item.capital) return null;
  12840. return { Date:date, Value:item.capital.total };
  12841. case 7:
  12842. case "EXCHANGE": //换手率 历史流通股本
  12843. if (!item.capital) return null;
  12844. return { Date:date, Value:item.capital.a };
  12845. default:
  12846. return null;
  12847. }
  12848. }
  12849. }
  12850. function DownloadGroupData(obj)
  12851. {
  12852. this.Url=obj.Url;
  12853. this.RealtimeUrl=obj.RealtimeUrl;
  12854. this.Job=obj.Job;
  12855. this.Symbol=obj.Symbol;
  12856. this.Args=obj.Args;
  12857. this.DataKey=obj.DataKey;
  12858. this.RecvCallback=obj.Callback;
  12859. this.ErrorCallback=obj.ErrorCallback;
  12860. this.Download=function()
  12861. {
  12862. var varName=this.Args[0];
  12863. switch(varName)
  12864. {
  12865. case "HYBLOCK":
  12866. case "DYBLOCK":
  12867. case "GNBLOCK":
  12868. this.DownloadGroupName(varName);
  12869. break;
  12870. }
  12871. }
  12872. this.DownloadGroupName=function(blockType)
  12873. {
  12874. var self=this;
  12875. var field=["name","symbol"];
  12876. if (blockType=="HYBLOCK") field.push("industry");
  12877. else if (blockType=="DYBLOCK") field.push("region");
  12878. else if (blockType=="GNBLOCK") field.push("concept");
  12879. JSNetwork.HttpRequest({
  12880. url: self.RealtimeUrl,
  12881. data:
  12882. {
  12883. "field": field,
  12884. "symbol": [this.Symbol]
  12885. },
  12886. method:"post",
  12887. dataType: "json",
  12888. async:true,
  12889. success: function (recvData)
  12890. {
  12891. var data=self.RecvGroupName(recvData.data);
  12892. self.RecvCallback(data, self.Job, self.DataKey, 1);
  12893. },
  12894. error: function(request)
  12895. {
  12896. self.ErrorCallback(request);
  12897. }
  12898. });
  12899. }
  12900. this.RecvGroupName=function(recvData)
  12901. {
  12902. if (!recvData.stock || recvData.stock.length!=1) return null;
  12903. var stock=recvData.stock[0];
  12904. var varName=this.Args[0];
  12905. var value=null;
  12906. if (varName=="HYBLOCK")
  12907. {
  12908. var industry=stock.industry;
  12909. if (!industry) return null;
  12910. var value;
  12911. for(var i in industry)
  12912. {
  12913. var item=industry[i];
  12914. value=item.name;
  12915. }
  12916. }
  12917. else if (varName=="DYBLOCK")
  12918. {
  12919. var region=stock.region;
  12920. if (!region) return null;
  12921. for(var i in region)
  12922. {
  12923. var item=region[i];
  12924. value=item.name;
  12925. }
  12926. }
  12927. else if (varName=="GNBLOCK")
  12928. {
  12929. var concept=stock.concept;
  12930. if (!concept) return null;
  12931. value="";
  12932. for(var i in concept)
  12933. {
  12934. var item=concept[i];
  12935. if (value.length>0) value+=' ';
  12936. value+=item.name;
  12937. }
  12938. }
  12939. return { Value:value };
  12940. }
  12941. }
  12942. /*
  12943. var code1='VARHIGH:IF(VAR1<=REF(HH,-1),REF(H,BARSLAST(VAR1>=REF(HH,1))),DRAWNULL),COLORYELLOW;';
  12944. var code2='VAR1=((SMA(MAX((CLOSE - LC),0),3,1) / SMA(ABS((CLOSE - LC)),3,1)) * 100);';
  12945. var code3='mm1=1-2*-9+20;';
  12946. JSConsole.Complier.Log(code1+code2)
  12947. var tokens=JSComplier.Tokenize(code1+code2);
  12948. var ast=JSComplier.Parse(code2+code1);
  12949. JSConsole.Complier.Log(ast);
  12950. */
  12951. var JSCommonComplier=
  12952. {
  12953. JSComplier: JSComplier,
  12954. g_JSComplierResource: g_JSComplierResource,
  12955. };
  12956. export
  12957. {
  12958. JSCommonComplier,
  12959. ErrorHandler,
  12960. JSComplier,
  12961. JSParser,
  12962. Syntax,
  12963. JS_EXECUTE_JOB_ID,
  12964. g_JSComplierResource,
  12965. };
  12966. /*
  12967. module.exports =
  12968. {
  12969. JSCommonComplier:
  12970. {
  12971. JSComplier: JSComplier,
  12972. g_JSComplierResource: g_JSComplierResource,
  12973. },
  12974. //单个类导出
  12975. JSCommonComplier_ErrorHandler: ErrorHandler,
  12976. JSCommonComplier_JSComplier:JSComplier,
  12977. JSCommonComplier_JSParser:JSParser,
  12978. JSCommonComplier_Syntax:Syntax,
  12979. JS_EXECUTE_JOB_ID:JS_EXECUTE_JOB_ID,
  12980. g_JSComplierResource:g_JSComplierResource,
  12981. };
  12982. */