commit a6bd00925cdaa4238a6cfa09f43c542d72ef63ed
Author: npmrun <1549469775@qq.com>
Date: Wed Sep 15 22:30:25 2021 +0800
init
diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000..5008ddf
Binary files /dev/null and b/.DS_Store differ
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b82fe55
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+node_modules
+unpackage
\ No newline at end of file
diff --git a/.hbuilderx/launch.json b/.hbuilderx/launch.json
new file mode 100644
index 0000000..07c1d5f
--- /dev/null
+++ b/.hbuilderx/launch.json
@@ -0,0 +1,16 @@
+{ // launch.json 配置了启动调试时相关设置,configurations下节点名称可为 app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/
+ // launchtype项可配置值为local或remote, local代表前端连本地云函数,remote代表前端连云端云函数
+ "version": "0.0",
+ "configurations": [{
+ "default" :
+ {
+ "launchtype" : "local"
+ },
+ "h5" :
+ {
+ "launchtype" : "local"
+ },
+ "type" : "uniCloud"
+ }
+ ]
+}
diff --git a/App.vue b/App.vue
new file mode 100644
index 0000000..8c2b732
--- /dev/null
+++ b/App.vue
@@ -0,0 +1,17 @@
+
+
+
diff --git a/components/HQChartControl/HQChartControl.vue b/components/HQChartControl/HQChartControl.vue
new file mode 100644
index 0000000..a5ed1cc
--- /dev/null
+++ b/components/HQChartControl/HQChartControl.vue
@@ -0,0 +1,341 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..b61f63e
--- /dev/null
+++ b/index.html
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/main.js b/main.js
new file mode 100644
index 0000000..ffd2f81
--- /dev/null
+++ b/main.js
@@ -0,0 +1,10 @@
+import App from './App'
+
+
+import Vue from 'vue'
+Vue.config.productionTip = false
+App.mpType = 'app'
+const app = new Vue({
+ ...App
+})
+app.$mount()
diff --git a/manifest.json b/manifest.json
new file mode 100644
index 0000000..74ebdee
--- /dev/null
+++ b/manifest.json
@@ -0,0 +1,72 @@
+{
+ "name" : "k_graph",
+ "appid" : "",
+ "description" : "",
+ "versionName" : "1.0.0",
+ "versionCode" : "100",
+ "transformPx" : false,
+ /* 5+App特有相关 */
+ "app-plus" : {
+ "usingComponents" : true,
+ "nvueStyleCompiler" : "uni-app",
+ "compilerVersion" : 3,
+ "splashscreen" : {
+ "alwaysShowBeforeRender" : true,
+ "waiting" : true,
+ "autoclose" : true,
+ "delay" : 0
+ },
+ /* 模块配置 */
+ "modules" : {},
+ /* 应用发布信息 */
+ "distribute" : {
+ /* android打包配置 */
+ "android" : {
+ "permissions" : [
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ]
+ },
+ /* ios打包配置 */
+ "ios" : {},
+ /* SDK配置 */
+ "sdkConfigs" : {}
+ }
+ },
+ /* 快应用特有相关 */
+ "quickapp" : {},
+ /* 小程序特有相关 */
+ "mp-weixin" : {
+ "appid" : "",
+ "setting" : {
+ "urlCheck" : false
+ },
+ "usingComponents" : true
+ },
+ "mp-alipay" : {
+ "usingComponents" : true
+ },
+ "mp-baidu" : {
+ "usingComponents" : true
+ },
+ "mp-toutiao" : {
+ "usingComponents" : true
+ },
+ "uniStatistics" : {
+ "enable" : false
+ },
+ "vueVersion" : "2"
+}
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..cc01a18
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,3286 @@
+{
+ "name": "k_graph",
+ "version": "1.0.0",
+ "lockfileVersion": 1,
+ "requires": true,
+ "dependencies": {
+ "acorn": {
+ "version": "5.7.4",
+ "resolved": "https://registry.nlark.com/acorn/download/acorn-5.7.4.tgz",
+ "integrity": "sha1-Po2KmUfQWZoXltECJddDL0pKz14="
+ },
+ "acorn-dynamic-import": {
+ "version": "2.0.2",
+ "resolved": "https://registry.nlark.com/acorn-dynamic-import/download/acorn-dynamic-import-2.0.2.tgz",
+ "integrity": "sha1-x1K9IQvvZ5UBtsbLf8hPj0cVjMQ=",
+ "requires": {
+ "acorn": "^4.0.3"
+ },
+ "dependencies": {
+ "acorn": {
+ "version": "4.0.13",
+ "resolved": "https://registry.nlark.com/acorn/download/acorn-4.0.13.tgz",
+ "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c="
+ }
+ }
+ },
+ "ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.nlark.com/ajv/download/ajv-6.12.6.tgz?cache=0&sync_timestamp=1631470912358&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fajv%2Fdownload%2Fajv-6.12.6.tgz",
+ "integrity": "sha1-uvWmLoArB9l3A0WG+MO69a3ybfQ=",
+ "requires": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "ajv-keywords": {
+ "version": "3.5.2",
+ "resolved": "https://registry.npm.taobao.org/ajv-keywords/download/ajv-keywords-3.5.2.tgz?cache=0&sync_timestamp=1616882441894&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fajv-keywords%2Fdownload%2Fajv-keywords-3.5.2.tgz",
+ "integrity": "sha1-MfKdpatuANHC0yms97WSlhTVAU0="
+ },
+ "align-text": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npm.taobao.org/align-text/download/align-text-0.1.4.tgz",
+ "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=",
+ "requires": {
+ "kind-of": "^3.0.2",
+ "longest": "^1.0.1",
+ "repeat-string": "^1.5.2"
+ }
+ },
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.nlark.com/ansi-regex/download/ansi-regex-2.1.1.tgz?cache=0&sync_timestamp=1631634988487&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fansi-regex%2Fdownload%2Fansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
+ },
+ "anymatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npm.taobao.org/anymatch/download/anymatch-3.1.2.tgz",
+ "integrity": "sha1-wFV8CWrzLxBhmPT04qODU343hxY=",
+ "optional": true,
+ "requires": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ }
+ },
+ "arr-diff": {
+ "version": "4.0.0",
+ "resolved": "https://registry.nlark.com/arr-diff/download/arr-diff-4.0.0.tgz",
+ "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=",
+ "optional": true
+ },
+ "arr-flatten": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npm.taobao.org/arr-flatten/download/arr-flatten-1.1.0.tgz",
+ "integrity": "sha1-NgSLv/TntH4TZkQxbJlmnqWukfE=",
+ "optional": true
+ },
+ "arr-union": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npm.taobao.org/arr-union/download/arr-union-3.1.0.tgz",
+ "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=",
+ "optional": true
+ },
+ "array-unique": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npm.taobao.org/array-unique/download/array-unique-0.3.2.tgz",
+ "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
+ "optional": true
+ },
+ "asn1.js": {
+ "version": "5.4.1",
+ "resolved": "https://registry.npm.taobao.org/asn1.js/download/asn1.js-5.4.1.tgz",
+ "integrity": "sha1-EamAuE67kXgc41sP3C7ilON4Pwc=",
+ "requires": {
+ "bn.js": "^4.0.0",
+ "inherits": "^2.0.1",
+ "minimalistic-assert": "^1.0.0",
+ "safer-buffer": "^2.1.0"
+ },
+ "dependencies": {
+ "bn.js": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npm.taobao.org/bn.js/download/bn.js-4.12.0.tgz",
+ "integrity": "sha1-d1s/J477uXGO7HNh9IP7Nvu/6og="
+ }
+ }
+ },
+ "assert": {
+ "version": "1.5.0",
+ "resolved": "https://registry.nlark.com/assert/download/assert-1.5.0.tgz?cache=0&sync_timestamp=1618847153747&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fassert%2Fdownload%2Fassert-1.5.0.tgz",
+ "integrity": "sha1-VcEJqvbgrv2z3EtxJAxwv1dLGOs=",
+ "requires": {
+ "object-assign": "^4.1.1",
+ "util": "0.10.3"
+ },
+ "dependencies": {
+ "inherits": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npm.taobao.org/inherits/download/inherits-2.0.1.tgz",
+ "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE="
+ },
+ "util": {
+ "version": "0.10.3",
+ "resolved": "https://registry.nlark.com/util/download/util-0.10.3.tgz?cache=0&sync_timestamp=1622212984161&other_urls=https%3A%2F%2Fregistry.nlark.com%2Futil%2Fdownload%2Futil-0.10.3.tgz",
+ "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=",
+ "requires": {
+ "inherits": "2.0.1"
+ }
+ }
+ }
+ },
+ "assign-symbols": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npm.taobao.org/assign-symbols/download/assign-symbols-1.0.0.tgz",
+ "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=",
+ "optional": true
+ },
+ "async": {
+ "version": "2.6.3",
+ "resolved": "https://registry.nlark.com/async/download/async-2.6.3.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fasync%2Fdownload%2Fasync-2.6.3.tgz",
+ "integrity": "sha1-1yYl4jRKNlbjo61Pp0n6gymdgv8=",
+ "requires": {
+ "lodash": "^4.17.14"
+ }
+ },
+ "async-each": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npm.taobao.org/async-each/download/async-each-1.0.3.tgz",
+ "integrity": "sha1-tyfb+H12UWAvBvTUrDh/R9kbDL8=",
+ "optional": true
+ },
+ "async-validator": {
+ "version": "1.8.5",
+ "resolved": "https://registry.nlark.com/async-validator/download/async-validator-1.8.5.tgz?cache=0&sync_timestamp=1630393256517&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fasync-validator%2Fdownload%2Fasync-validator-1.8.5.tgz",
+ "integrity": "sha1-3D4I7B/Q3dtn5ghC8CwM0c7G1/A=",
+ "requires": {
+ "babel-runtime": "6.x"
+ }
+ },
+ "atob": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npm.taobao.org/atob/download/atob-2.1.2.tgz",
+ "integrity": "sha1-bZUX654DDSQ2ZmZR6GvZ9vE1M8k=",
+ "optional": true
+ },
+ "axios": {
+ "version": "0.16.2",
+ "resolved": "https://registry.nlark.com/axios/download/axios-0.16.2.tgz?cache=0&sync_timestamp=1630942582656&other_urls=https%3A%2F%2Fregistry.nlark.com%2Faxios%2Fdownload%2Faxios-0.16.2.tgz",
+ "integrity": "sha1-uk+S8XFn37q0CYN4VFS5rBScPG0=",
+ "requires": {
+ "follow-redirects": "^1.2.3",
+ "is-buffer": "^1.1.5"
+ }
+ },
+ "babel-helper-vue-jsx-merge-props": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npm.taobao.org/babel-helper-vue-jsx-merge-props/download/babel-helper-vue-jsx-merge-props-2.0.3.tgz",
+ "integrity": "sha1-Iq69OzOQIyjlEyk6jkmSs4T58bY="
+ },
+ "babel-runtime": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npm.taobao.org/babel-runtime/download/babel-runtime-6.26.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbabel-runtime%2Fdownload%2Fbabel-runtime-6.26.0.tgz",
+ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
+ "requires": {
+ "core-js": "^2.4.0",
+ "regenerator-runtime": "^0.11.0"
+ }
+ },
+ "base": {
+ "version": "0.11.2",
+ "resolved": "https://registry.npm.taobao.org/base/download/base-0.11.2.tgz",
+ "integrity": "sha1-e95c7RRbbVUakNuH+DxVi060io8=",
+ "optional": true,
+ "requires": {
+ "cache-base": "^1.0.1",
+ "class-utils": "^0.3.5",
+ "component-emitter": "^1.2.1",
+ "define-property": "^1.0.0",
+ "isobject": "^3.0.1",
+ "mixin-deep": "^1.2.0",
+ "pascalcase": "^0.1.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "optional": true,
+ "requires": {
+ "is-descriptor": "^1.0.0"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npm.taobao.org/is-accessor-descriptor/download/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=",
+ "optional": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npm.taobao.org/is-data-descriptor/download/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=",
+ "optional": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npm.taobao.org/is-descriptor/download/is-descriptor-1.0.2.tgz",
+ "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=",
+ "optional": true,
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ },
+ "kind-of": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npm.taobao.org/kind-of/download/kind-of-6.0.3.tgz",
+ "integrity": "sha1-B8BQNKbDSfoG4k+jWqdttFgM5N0=",
+ "optional": true
+ }
+ }
+ },
+ "base64-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npm.taobao.org/base64-js/download/base64-js-1.5.1.tgz?cache=0&sync_timestamp=1605123440207&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbase64-js%2Fdownload%2Fbase64-js-1.5.1.tgz",
+ "integrity": "sha1-GxtEAWClv3rUC2UPCVljSBkDkwo="
+ },
+ "big.js": {
+ "version": "5.2.2",
+ "resolved": "https://registry.nlark.com/big.js/download/big.js-5.2.2.tgz",
+ "integrity": "sha1-ZfCvOC9Xi83HQr2cKB6cstd2gyg="
+ },
+ "binary-extensions": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npm.taobao.org/binary-extensions/download/binary-extensions-2.2.0.tgz?cache=0&sync_timestamp=1610299308660&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbinary-extensions%2Fdownload%2Fbinary-extensions-2.2.0.tgz",
+ "integrity": "sha1-dfUC7q+f/eQvyYgpZFvk6na9ni0=",
+ "optional": true
+ },
+ "bindings": {
+ "version": "1.5.0",
+ "resolved": "https://registry.nlark.com/bindings/download/bindings-1.5.0.tgz",
+ "integrity": "sha1-EDU8npRTNLwFEabZCzj7x8nFBN8=",
+ "optional": true,
+ "requires": {
+ "file-uri-to-path": "1.0.0"
+ }
+ },
+ "bn.js": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npm.taobao.org/bn.js/download/bn.js-5.2.0.tgz",
+ "integrity": "sha1-NYhgZ0OWxpl3canQUfzBtX1K4AI="
+ },
+ "braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npm.taobao.org/braces/download/braces-3.0.2.tgz",
+ "integrity": "sha1-NFThpGLujVmeI23zNs2epPiv4Qc=",
+ "optional": true,
+ "requires": {
+ "fill-range": "^7.0.1"
+ }
+ },
+ "brorand": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npm.taobao.org/brorand/download/brorand-1.1.0.tgz",
+ "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8="
+ },
+ "browserify-aes": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npm.taobao.org/browserify-aes/download/browserify-aes-1.2.0.tgz",
+ "integrity": "sha1-Mmc0ZC9APavDADIJhTu3CtQo70g=",
+ "requires": {
+ "buffer-xor": "^1.0.3",
+ "cipher-base": "^1.0.0",
+ "create-hash": "^1.1.0",
+ "evp_bytestokey": "^1.0.3",
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "browserify-cipher": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npm.taobao.org/browserify-cipher/download/browserify-cipher-1.0.1.tgz",
+ "integrity": "sha1-jWR0wbhwv9q807z8wZNKEOlPFfA=",
+ "requires": {
+ "browserify-aes": "^1.0.4",
+ "browserify-des": "^1.0.0",
+ "evp_bytestokey": "^1.0.0"
+ }
+ },
+ "browserify-des": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npm.taobao.org/browserify-des/download/browserify-des-1.0.2.tgz",
+ "integrity": "sha1-OvTx9Zg5QDVy8cZiBDdfen9wPpw=",
+ "requires": {
+ "cipher-base": "^1.0.1",
+ "des.js": "^1.0.0",
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.1.2"
+ }
+ },
+ "browserify-rsa": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npm.taobao.org/browserify-rsa/download/browserify-rsa-4.1.0.tgz",
+ "integrity": "sha1-sv0Gtbda4pf3zi3GUfkY9b4VjI0=",
+ "requires": {
+ "bn.js": "^5.0.0",
+ "randombytes": "^2.0.1"
+ }
+ },
+ "browserify-sign": {
+ "version": "4.2.1",
+ "resolved": "https://registry.nlark.com/browserify-sign/download/browserify-sign-4.2.1.tgz",
+ "integrity": "sha1-6vSt1G3VS+O7OzbAzxWrvrp5VsM=",
+ "requires": {
+ "bn.js": "^5.1.1",
+ "browserify-rsa": "^4.0.1",
+ "create-hash": "^1.2.0",
+ "create-hmac": "^1.1.7",
+ "elliptic": "^6.5.3",
+ "inherits": "^2.0.4",
+ "parse-asn1": "^5.1.5",
+ "readable-stream": "^3.6.0",
+ "safe-buffer": "^5.2.0"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-3.6.0.tgz",
+ "integrity": "sha1-M3u9o63AcGvT4CRCaihtS0sskZg=",
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.2.1.tgz",
+ "integrity": "sha1-Hq+fqb2x/dTsdfWPnNtOa3gn7sY="
+ }
+ }
+ },
+ "browserify-zlib": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npm.taobao.org/browserify-zlib/download/browserify-zlib-0.2.0.tgz",
+ "integrity": "sha1-KGlFnZqjviRf6P4sofRuLn9U1z8=",
+ "requires": {
+ "pako": "~1.0.5"
+ }
+ },
+ "buffer": {
+ "version": "4.9.2",
+ "resolved": "https://registry.npm.taobao.org/buffer/download/buffer-4.9.2.tgz?cache=0&sync_timestamp=1606098159535&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbuffer%2Fdownload%2Fbuffer-4.9.2.tgz",
+ "integrity": "sha1-Iw6tNEACmIZEhBqwJEr4xEu+Pvg=",
+ "requires": {
+ "base64-js": "^1.0.2",
+ "ieee754": "^1.1.4",
+ "isarray": "^1.0.0"
+ }
+ },
+ "buffer-xor": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npm.taobao.org/buffer-xor/download/buffer-xor-1.0.3.tgz",
+ "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk="
+ },
+ "builtin-status-codes": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npm.taobao.org/builtin-status-codes/download/builtin-status-codes-3.0.0.tgz",
+ "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug="
+ },
+ "cache-base": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npm.taobao.org/cache-base/download/cache-base-1.0.1.tgz",
+ "integrity": "sha1-Cn9GQWgxyLZi7jb+TnxZ129marI=",
+ "optional": true,
+ "requires": {
+ "collection-visit": "^1.0.0",
+ "component-emitter": "^1.2.1",
+ "get-value": "^2.0.6",
+ "has-value": "^1.0.0",
+ "isobject": "^3.0.1",
+ "set-value": "^2.0.0",
+ "to-object-path": "^0.3.0",
+ "union-value": "^1.0.0",
+ "unset-value": "^1.0.0"
+ }
+ },
+ "call-bind": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npm.taobao.org/call-bind/download/call-bind-1.0.2.tgz",
+ "integrity": "sha1-sdTonmiBGcPJqQOtMKuy9qkZvjw=",
+ "requires": {
+ "function-bind": "^1.1.1",
+ "get-intrinsic": "^1.0.2"
+ }
+ },
+ "camelcase": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npm.taobao.org/camelcase/download/camelcase-1.2.1.tgz?cache=0&sync_timestamp=1603923709404&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcamelcase%2Fdownload%2Fcamelcase-1.2.1.tgz",
+ "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk="
+ },
+ "center-align": {
+ "version": "0.1.3",
+ "resolved": "https://registry.nlark.com/center-align/download/center-align-0.1.3.tgz",
+ "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=",
+ "requires": {
+ "align-text": "^0.1.3",
+ "lazy-cache": "^1.0.3"
+ }
+ },
+ "chokidar": {
+ "version": "3.5.2",
+ "resolved": "https://registry.nlark.com/chokidar/download/chokidar-3.5.2.tgz",
+ "integrity": "sha1-26OXb8rbAW9m/TZQIdkWANAcHnU=",
+ "optional": true,
+ "requires": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "fsevents": "~2.3.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ }
+ },
+ "cipher-base": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npm.taobao.org/cipher-base/download/cipher-base-1.0.4.tgz",
+ "integrity": "sha1-h2Dk7MJy9MNjUy+SbYdKriwTl94=",
+ "requires": {
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "class-utils": {
+ "version": "0.3.6",
+ "resolved": "https://registry.nlark.com/class-utils/download/class-utils-0.3.6.tgz",
+ "integrity": "sha1-+TNprouafOAv1B+q0MqDAzGQxGM=",
+ "optional": true,
+ "requires": {
+ "arr-union": "^3.1.0",
+ "define-property": "^0.2.5",
+ "isobject": "^3.0.0",
+ "static-extend": "^0.1.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "optional": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ }
+ }
+ },
+ "cliui": {
+ "version": "2.1.0",
+ "resolved": "https://registry.nlark.com/cliui/download/cliui-2.1.0.tgz",
+ "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=",
+ "requires": {
+ "center-align": "^0.1.1",
+ "right-align": "^0.1.1",
+ "wordwrap": "0.0.2"
+ }
+ },
+ "code-point-at": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npm.taobao.org/code-point-at/download/code-point-at-1.1.0.tgz",
+ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
+ },
+ "collection-visit": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npm.taobao.org/collection-visit/download/collection-visit-1.0.0.tgz",
+ "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=",
+ "optional": true,
+ "requires": {
+ "map-visit": "^1.0.0",
+ "object-visit": "^1.0.0"
+ }
+ },
+ "component-emitter": {
+ "version": "1.3.0",
+ "resolved": "https://registry.nlark.com/component-emitter/download/component-emitter-1.3.0.tgz",
+ "integrity": "sha1-FuQHD7qK4ptnnyIVhT7hgasuq8A=",
+ "optional": true
+ },
+ "console-browserify": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npm.taobao.org/console-browserify/download/console-browserify-1.2.0.tgz",
+ "integrity": "sha1-ZwY871fOts9Jk6KrOlWECujEkzY="
+ },
+ "constants-browserify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.nlark.com/constants-browserify/download/constants-browserify-1.0.0.tgz",
+ "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U="
+ },
+ "copy-descriptor": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npm.taobao.org/copy-descriptor/download/copy-descriptor-0.1.1.tgz",
+ "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=",
+ "optional": true
+ },
+ "core-js": {
+ "version": "2.6.12",
+ "resolved": "https://registry.nlark.com/core-js/download/core-js-2.6.12.tgz",
+ "integrity": "sha1-2TM9+nsGXjR8xWgiGdb2kIWcwuw="
+ },
+ "core-util-is": {
+ "version": "1.0.3",
+ "resolved": "https://registry.nlark.com/core-util-is/download/core-util-is-1.0.3.tgz",
+ "integrity": "sha1-pgQtNjTCsn6TKPg3uWX6yDgI24U="
+ },
+ "create-ecdh": {
+ "version": "4.0.4",
+ "resolved": "https://registry.nlark.com/create-ecdh/download/create-ecdh-4.0.4.tgz",
+ "integrity": "sha1-1uf0v/pmc2CFoHYv06YyaE2rzE4=",
+ "requires": {
+ "bn.js": "^4.1.0",
+ "elliptic": "^6.5.3"
+ },
+ "dependencies": {
+ "bn.js": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npm.taobao.org/bn.js/download/bn.js-4.12.0.tgz",
+ "integrity": "sha1-d1s/J477uXGO7HNh9IP7Nvu/6og="
+ }
+ }
+ },
+ "create-hash": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npm.taobao.org/create-hash/download/create-hash-1.2.0.tgz",
+ "integrity": "sha1-iJB4rxGmN1a8+1m9IhmWvjqe8ZY=",
+ "requires": {
+ "cipher-base": "^1.0.1",
+ "inherits": "^2.0.1",
+ "md5.js": "^1.3.4",
+ "ripemd160": "^2.0.1",
+ "sha.js": "^2.4.0"
+ }
+ },
+ "create-hmac": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npm.taobao.org/create-hmac/download/create-hmac-1.1.7.tgz",
+ "integrity": "sha1-aRcMeLOrlXFHsriwRXLkfq0iQ/8=",
+ "requires": {
+ "cipher-base": "^1.0.3",
+ "create-hash": "^1.1.0",
+ "inherits": "^2.0.1",
+ "ripemd160": "^2.0.0",
+ "safe-buffer": "^5.0.1",
+ "sha.js": "^2.4.8"
+ }
+ },
+ "cross-spawn": {
+ "version": "5.1.0",
+ "resolved": "https://registry.nlark.com/cross-spawn/download/cross-spawn-5.1.0.tgz",
+ "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
+ "requires": {
+ "lru-cache": "^4.0.1",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ }
+ },
+ "crypto-browserify": {
+ "version": "3.12.0",
+ "resolved": "https://registry.npm.taobao.org/crypto-browserify/download/crypto-browserify-3.12.0.tgz",
+ "integrity": "sha1-OWz58xN/A+S45TLFj2mCVOAPgOw=",
+ "requires": {
+ "browserify-cipher": "^1.0.0",
+ "browserify-sign": "^4.0.0",
+ "create-ecdh": "^4.0.0",
+ "create-hash": "^1.1.0",
+ "create-hmac": "^1.1.0",
+ "diffie-hellman": "^5.0.0",
+ "inherits": "^2.0.1",
+ "pbkdf2": "^3.0.3",
+ "public-encrypt": "^4.0.0",
+ "randombytes": "^2.0.0",
+ "randomfill": "^1.0.3"
+ }
+ },
+ "d": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npm.taobao.org/d/download/d-1.0.1.tgz",
+ "integrity": "sha1-hpgJU3LVjb7jRv/Qxwk/mfj561o=",
+ "requires": {
+ "es5-ext": "^0.10.50",
+ "type": "^1.0.1"
+ }
+ },
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.nlark.com/debug/download/debug-2.6.9.tgz",
+ "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=",
+ "optional": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npm.taobao.org/decamelize/download/decamelize-1.2.0.tgz",
+ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
+ },
+ "decode-uri-component": {
+ "version": "0.2.0",
+ "resolved": "https://registry.nlark.com/decode-uri-component/download/decode-uri-component-0.2.0.tgz",
+ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
+ "optional": true
+ },
+ "deepmerge": {
+ "version": "1.5.2",
+ "resolved": "https://registry.npm.taobao.org/deepmerge/download/deepmerge-1.5.2.tgz",
+ "integrity": "sha1-EEmdhohEza1P7ghC34x/bwyVp1M="
+ },
+ "define-property": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-2.0.2.tgz",
+ "integrity": "sha1-1Flono1lS6d+AqgX+HENcCyxbp0=",
+ "optional": true,
+ "requires": {
+ "is-descriptor": "^1.0.2",
+ "isobject": "^3.0.1"
+ },
+ "dependencies": {
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npm.taobao.org/is-accessor-descriptor/download/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=",
+ "optional": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npm.taobao.org/is-data-descriptor/download/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=",
+ "optional": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npm.taobao.org/is-descriptor/download/is-descriptor-1.0.2.tgz",
+ "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=",
+ "optional": true,
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ },
+ "kind-of": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npm.taobao.org/kind-of/download/kind-of-6.0.3.tgz",
+ "integrity": "sha1-B8BQNKbDSfoG4k+jWqdttFgM5N0=",
+ "optional": true
+ }
+ }
+ },
+ "des.js": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npm.taobao.org/des.js/download/des.js-1.0.1.tgz",
+ "integrity": "sha1-U4IULhvcU/hdhtU+X0qn3rkeCEM=",
+ "requires": {
+ "inherits": "^2.0.1",
+ "minimalistic-assert": "^1.0.0"
+ }
+ },
+ "diffie-hellman": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npm.taobao.org/diffie-hellman/download/diffie-hellman-5.0.3.tgz",
+ "integrity": "sha1-QOjumPVaIUlgcUaSHGPhrl89KHU=",
+ "requires": {
+ "bn.js": "^4.1.0",
+ "miller-rabin": "^4.0.0",
+ "randombytes": "^2.0.0"
+ },
+ "dependencies": {
+ "bn.js": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npm.taobao.org/bn.js/download/bn.js-4.12.0.tgz",
+ "integrity": "sha1-d1s/J477uXGO7HNh9IP7Nvu/6og="
+ }
+ }
+ },
+ "domain-browser": {
+ "version": "1.2.0",
+ "resolved": "https://registry.nlark.com/domain-browser/download/domain-browser-1.2.0.tgz?cache=0&sync_timestamp=1627591557212&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fdomain-browser%2Fdownload%2Fdomain-browser-1.2.0.tgz",
+ "integrity": "sha1-PTH1AZGmdJ3RN1p/Ui6CPULlTto="
+ },
+ "echarts": {
+ "version": "4.9.0",
+ "resolved": "https://registry.nlark.com/echarts/download/echarts-4.9.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fecharts%2Fdownload%2Fecharts-4.9.0.tgz",
+ "integrity": "sha1-qbm6oD8Doqcx5jQMVb77V6nhNH0=",
+ "requires": {
+ "zrender": "4.3.2"
+ }
+ },
+ "element-ui": {
+ "version": "1.4.13",
+ "resolved": "https://registry.nlark.com/element-ui/download/element-ui-1.4.13.tgz",
+ "integrity": "sha1-0LBVmHrwy5N6ETW6v0NgroDUoSE=",
+ "requires": {
+ "async-validator": "~1.8.1",
+ "babel-helper-vue-jsx-merge-props": "^2.0.0",
+ "deepmerge": "^1.2.0",
+ "throttle-debounce": "^1.0.1"
+ }
+ },
+ "elliptic": {
+ "version": "6.5.4",
+ "resolved": "https://registry.npm.taobao.org/elliptic/download/elliptic-6.5.4.tgz",
+ "integrity": "sha1-2jfOvTHnmhNn6UG1ku0fvr1Yq7s=",
+ "requires": {
+ "bn.js": "^4.11.9",
+ "brorand": "^1.1.0",
+ "hash.js": "^1.0.0",
+ "hmac-drbg": "^1.0.1",
+ "inherits": "^2.0.4",
+ "minimalistic-assert": "^1.0.1",
+ "minimalistic-crypto-utils": "^1.0.1"
+ },
+ "dependencies": {
+ "bn.js": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npm.taobao.org/bn.js/download/bn.js-4.12.0.tgz",
+ "integrity": "sha1-d1s/J477uXGO7HNh9IP7Nvu/6og="
+ }
+ }
+ },
+ "emojis-list": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npm.taobao.org/emojis-list/download/emojis-list-3.0.0.tgz",
+ "integrity": "sha1-VXBmIEatKeLpFucariYKvf9Pang="
+ },
+ "enhanced-resolve": {
+ "version": "3.4.1",
+ "resolved": "https://registry.nlark.com/enhanced-resolve/download/enhanced-resolve-3.4.1.tgz",
+ "integrity": "sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24=",
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "memory-fs": "^0.4.0",
+ "object-assign": "^4.0.1",
+ "tapable": "^0.2.7"
+ }
+ },
+ "errno": {
+ "version": "0.1.8",
+ "resolved": "https://registry.npm.taobao.org/errno/download/errno-0.1.8.tgz",
+ "integrity": "sha1-i7Ppx9Rjvkl2/4iPdrSAnrwugR8=",
+ "requires": {
+ "prr": "~1.0.1"
+ }
+ },
+ "error-ex": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npm.taobao.org/error-ex/download/error-ex-1.3.2.tgz",
+ "integrity": "sha1-tKxAZIEH/c3PriQvQovqihTU8b8=",
+ "requires": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "es5-ext": {
+ "version": "0.10.53",
+ "resolved": "https://registry.nlark.com/es5-ext/download/es5-ext-0.10.53.tgz",
+ "integrity": "sha1-k8WjrP2+8nUiCtcmRK0C7hg2jeE=",
+ "requires": {
+ "es6-iterator": "~2.0.3",
+ "es6-symbol": "~3.1.3",
+ "next-tick": "~1.0.0"
+ }
+ },
+ "es6-iterator": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npm.taobao.org/es6-iterator/download/es6-iterator-2.0.3.tgz",
+ "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=",
+ "requires": {
+ "d": "1",
+ "es5-ext": "^0.10.35",
+ "es6-symbol": "^3.1.1"
+ }
+ },
+ "es6-map": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npm.taobao.org/es6-map/download/es6-map-0.1.5.tgz",
+ "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=",
+ "requires": {
+ "d": "1",
+ "es5-ext": "~0.10.14",
+ "es6-iterator": "~2.0.1",
+ "es6-set": "~0.1.5",
+ "es6-symbol": "~3.1.1",
+ "event-emitter": "~0.3.5"
+ }
+ },
+ "es6-set": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npm.taobao.org/es6-set/download/es6-set-0.1.5.tgz",
+ "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=",
+ "requires": {
+ "d": "1",
+ "es5-ext": "~0.10.14",
+ "es6-iterator": "~2.0.1",
+ "es6-symbol": "3.1.1",
+ "event-emitter": "~0.3.5"
+ },
+ "dependencies": {
+ "es6-symbol": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npm.taobao.org/es6-symbol/download/es6-symbol-3.1.1.tgz",
+ "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=",
+ "requires": {
+ "d": "1",
+ "es5-ext": "~0.10.14"
+ }
+ }
+ }
+ },
+ "es6-symbol": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npm.taobao.org/es6-symbol/download/es6-symbol-3.1.3.tgz",
+ "integrity": "sha1-utXTwbzawoJp9MszHkMceKxwXRg=",
+ "requires": {
+ "d": "^1.0.1",
+ "ext": "^1.1.2"
+ }
+ },
+ "es6-weak-map": {
+ "version": "2.0.3",
+ "resolved": "https://registry.nlark.com/es6-weak-map/download/es6-weak-map-2.0.3.tgz",
+ "integrity": "sha1-ttofFswswNm+Q+a9v8Xn383zHVM=",
+ "requires": {
+ "d": "1",
+ "es5-ext": "^0.10.46",
+ "es6-iterator": "^2.0.3",
+ "es6-symbol": "^3.1.1"
+ }
+ },
+ "escope": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npm.taobao.org/escope/download/escope-3.6.0.tgz",
+ "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=",
+ "requires": {
+ "es6-map": "^0.1.3",
+ "es6-weak-map": "^2.0.1",
+ "esrecurse": "^4.1.0",
+ "estraverse": "^4.1.1"
+ }
+ },
+ "esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.nlark.com/esrecurse/download/esrecurse-4.3.0.tgz",
+ "integrity": "sha1-eteWTWeauyi+5yzsY3WLHF0smSE=",
+ "requires": {
+ "estraverse": "^5.2.0"
+ },
+ "dependencies": {
+ "estraverse": {
+ "version": "5.2.0",
+ "resolved": "https://registry.nlark.com/estraverse/download/estraverse-5.2.0.tgz?cache=0&sync_timestamp=1622604531280&other_urls=https%3A%2F%2Fregistry.nlark.com%2Festraverse%2Fdownload%2Festraverse-5.2.0.tgz",
+ "integrity": "sha1-MH30JUfmzHMk088DwVXVzbjFOIA="
+ }
+ }
+ },
+ "estraverse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.nlark.com/estraverse/download/estraverse-4.3.0.tgz?cache=0&sync_timestamp=1622604531280&other_urls=https%3A%2F%2Fregistry.nlark.com%2Festraverse%2Fdownload%2Festraverse-4.3.0.tgz",
+ "integrity": "sha1-OYrT88WiSUi+dyXoPRGn3ijNvR0="
+ },
+ "event-emitter": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npm.taobao.org/event-emitter/download/event-emitter-0.3.5.tgz",
+ "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=",
+ "requires": {
+ "d": "1",
+ "es5-ext": "~0.10.14"
+ }
+ },
+ "events": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npm.taobao.org/events/download/events-3.3.0.tgz",
+ "integrity": "sha1-Mala0Kkk4tLEGagTrrLE6HjqdAA="
+ },
+ "evp_bytestokey": {
+ "version": "1.0.3",
+ "resolved": "https://registry.nlark.com/evp_bytestokey/download/evp_bytestokey-1.0.3.tgz",
+ "integrity": "sha1-f8vbGY3HGVlDLv4ThCaE4FJaywI=",
+ "requires": {
+ "md5.js": "^1.3.4",
+ "safe-buffer": "^5.1.1"
+ }
+ },
+ "execa": {
+ "version": "0.7.0",
+ "resolved": "https://registry.nlark.com/execa/download/execa-0.7.0.tgz?cache=0&sync_timestamp=1622825396605&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fexeca%2Fdownload%2Fexeca-0.7.0.tgz",
+ "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=",
+ "requires": {
+ "cross-spawn": "^5.0.1",
+ "get-stream": "^3.0.0",
+ "is-stream": "^1.1.0",
+ "npm-run-path": "^2.0.0",
+ "p-finally": "^1.0.0",
+ "signal-exit": "^3.0.0",
+ "strip-eof": "^1.0.0"
+ }
+ },
+ "expand-brackets": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npm.taobao.org/expand-brackets/download/expand-brackets-2.1.4.tgz",
+ "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
+ "optional": true,
+ "requires": {
+ "debug": "^2.3.3",
+ "define-property": "^0.2.5",
+ "extend-shallow": "^2.0.1",
+ "posix-character-classes": "^0.1.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "optional": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npm.taobao.org/extend-shallow/download/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "optional": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "ext": {
+ "version": "1.5.0",
+ "resolved": "https://registry.nlark.com/ext/download/ext-1.5.0.tgz",
+ "integrity": "sha1-6TuXrgyyP4NwOA9hB9LSt4h2h60=",
+ "requires": {
+ "type": "^2.5.0"
+ },
+ "dependencies": {
+ "type": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npm.taobao.org/type/download/type-2.5.0.tgz",
+ "integrity": "sha1-Ci54wud5B7JSq+XymMGwHGPw2z0="
+ }
+ }
+ },
+ "extend-shallow": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npm.taobao.org/extend-shallow/download/extend-shallow-3.0.2.tgz",
+ "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
+ "optional": true,
+ "requires": {
+ "assign-symbols": "^1.0.0",
+ "is-extendable": "^1.0.1"
+ },
+ "dependencies": {
+ "is-extendable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npm.taobao.org/is-extendable/download/is-extendable-1.0.1.tgz",
+ "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=",
+ "optional": true,
+ "requires": {
+ "is-plain-object": "^2.0.4"
+ }
+ }
+ }
+ },
+ "extglob": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npm.taobao.org/extglob/download/extglob-2.0.4.tgz",
+ "integrity": "sha1-rQD+TcYSqSMuhxhxHcXLWrAoVUM=",
+ "optional": true,
+ "requires": {
+ "array-unique": "^0.3.2",
+ "define-property": "^1.0.0",
+ "expand-brackets": "^2.1.4",
+ "extend-shallow": "^2.0.1",
+ "fragment-cache": "^0.2.1",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "optional": true,
+ "requires": {
+ "is-descriptor": "^1.0.0"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npm.taobao.org/extend-shallow/download/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "optional": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npm.taobao.org/is-accessor-descriptor/download/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=",
+ "optional": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npm.taobao.org/is-data-descriptor/download/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=",
+ "optional": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npm.taobao.org/is-descriptor/download/is-descriptor-1.0.2.tgz",
+ "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=",
+ "optional": true,
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ },
+ "kind-of": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npm.taobao.org/kind-of/download/kind-of-6.0.3.tgz",
+ "integrity": "sha1-B8BQNKbDSfoG4k+jWqdttFgM5N0=",
+ "optional": true
+ }
+ }
+ },
+ "fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npm.taobao.org/fast-deep-equal/download/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha1-On1WtVnWy8PrUSMlJE5hmmXGxSU="
+ },
+ "fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.nlark.com/fast-json-stable-stringify/download/fast-json-stable-stringify-2.1.0.tgz?cache=0&sync_timestamp=1624543041215&other_urls=https%3A%2F%2Fregistry.nlark.com%2Ffast-json-stable-stringify%2Fdownload%2Ffast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha1-h0v2nG9ATCtdmcSBNBOZ/VWJJjM="
+ },
+ "file-uri-to-path": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npm.taobao.org/file-uri-to-path/download/file-uri-to-path-1.0.0.tgz",
+ "integrity": "sha1-VTp7hEb/b2hDWcRF8eN6BdrMM90=",
+ "optional": true
+ },
+ "fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.nlark.com/fill-range/download/fill-range-7.0.1.tgz",
+ "integrity": "sha1-GRmmp8df44ssfHflGYU12prN2kA=",
+ "optional": true,
+ "requires": {
+ "to-regex-range": "^5.0.1"
+ }
+ },
+ "find-up": {
+ "version": "2.1.0",
+ "resolved": "https://registry.nlark.com/find-up/download/find-up-2.1.0.tgz",
+ "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
+ "requires": {
+ "locate-path": "^2.0.0"
+ }
+ },
+ "follow-redirects": {
+ "version": "1.14.4",
+ "resolved": "https://registry.nlark.com/follow-redirects/download/follow-redirects-1.14.4.tgz",
+ "integrity": "sha1-g4/fSKi73XnlLuUfsclOPtmLk3k="
+ },
+ "for-in": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npm.taobao.org/for-in/download/for-in-1.0.2.tgz",
+ "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
+ "optional": true
+ },
+ "fragment-cache": {
+ "version": "0.2.1",
+ "resolved": "https://registry.nlark.com/fragment-cache/download/fragment-cache-0.2.1.tgz",
+ "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
+ "optional": true,
+ "requires": {
+ "map-cache": "^0.2.2"
+ }
+ },
+ "fsevents": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npm.taobao.org/fsevents/download/fsevents-2.3.2.tgz?cache=0&sync_timestamp=1612536512306&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffsevents%2Fdownload%2Ffsevents-2.3.2.tgz",
+ "integrity": "sha1-ilJveLj99GI7cJ4Ll1xSwkwC/Ro=",
+ "optional": true
+ },
+ "function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npm.taobao.org/function-bind/download/function-bind-1.1.1.tgz",
+ "integrity": "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0="
+ },
+ "get-caller-file": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npm.taobao.org/get-caller-file/download/get-caller-file-1.0.3.tgz",
+ "integrity": "sha1-+Xj6TJDR3+f/LWvtoqUV5xO9z0o="
+ },
+ "get-intrinsic": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npm.taobao.org/get-intrinsic/download/get-intrinsic-1.1.1.tgz",
+ "integrity": "sha1-FfWfN2+FXERpY5SPDSTNNje0q8Y=",
+ "requires": {
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.1"
+ }
+ },
+ "get-stream": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npm.taobao.org/get-stream/download/get-stream-3.0.0.tgz",
+ "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ="
+ },
+ "get-value": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npm.taobao.org/get-value/download/get-value-2.0.6.tgz",
+ "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=",
+ "optional": true
+ },
+ "glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.nlark.com/glob-parent/download/glob-parent-5.1.2.tgz?cache=0&sync_timestamp=1626760165717&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fglob-parent%2Fdownload%2Fglob-parent-5.1.2.tgz",
+ "integrity": "sha1-hpgyxYA0/mikCTwX3BXoNA2EAcQ=",
+ "optional": true,
+ "requires": {
+ "is-glob": "^4.0.1"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.2.8",
+ "resolved": "https://registry.nlark.com/graceful-fs/download/graceful-fs-4.2.8.tgz?cache=0&sync_timestamp=1628194078324&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fgraceful-fs%2Fdownload%2Fgraceful-fs-4.2.8.tgz",
+ "integrity": "sha1-5BK40z9eAGWTy9PO5t+fLOu+gCo="
+ },
+ "has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.nlark.com/has/download/has-1.0.3.tgz",
+ "integrity": "sha1-ci18v8H2qoJB8W3YFOAR4fQeh5Y=",
+ "requires": {
+ "function-bind": "^1.1.1"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.nlark.com/has-flag/download/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
+ },
+ "has-symbols": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npm.taobao.org/has-symbols/download/has-symbols-1.0.2.tgz",
+ "integrity": "sha1-Fl0wcMADCXUqEjakeTMeOsVvFCM="
+ },
+ "has-value": {
+ "version": "1.0.0",
+ "resolved": "https://registry.nlark.com/has-value/download/has-value-1.0.0.tgz",
+ "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=",
+ "optional": true,
+ "requires": {
+ "get-value": "^2.0.6",
+ "has-values": "^1.0.0",
+ "isobject": "^3.0.0"
+ }
+ },
+ "has-values": {
+ "version": "1.0.0",
+ "resolved": "https://registry.nlark.com/has-values/download/has-values-1.0.0.tgz",
+ "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=",
+ "optional": true,
+ "requires": {
+ "is-number": "^3.0.0",
+ "kind-of": "^4.0.0"
+ },
+ "dependencies": {
+ "is-number": {
+ "version": "3.0.0",
+ "resolved": "https://registry.nlark.com/is-number/download/is-number-3.0.0.tgz",
+ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+ "optional": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npm.taobao.org/kind-of/download/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "optional": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "kind-of": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npm.taobao.org/kind-of/download/kind-of-4.0.0.tgz",
+ "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
+ "optional": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "hash-base": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npm.taobao.org/hash-base/download/hash-base-3.1.0.tgz",
+ "integrity": "sha1-VcOB2eBuHSmXqIO0o/3f5/DTrzM=",
+ "requires": {
+ "inherits": "^2.0.4",
+ "readable-stream": "^3.6.0",
+ "safe-buffer": "^5.2.0"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-3.6.0.tgz",
+ "integrity": "sha1-M3u9o63AcGvT4CRCaihtS0sskZg=",
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.2.1.tgz",
+ "integrity": "sha1-Hq+fqb2x/dTsdfWPnNtOa3gn7sY="
+ }
+ }
+ },
+ "hash.js": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npm.taobao.org/hash.js/download/hash.js-1.1.7.tgz",
+ "integrity": "sha1-C6vKU46NTuSg+JiNaIZlN6ADz0I=",
+ "requires": {
+ "inherits": "^2.0.3",
+ "minimalistic-assert": "^1.0.1"
+ }
+ },
+ "hmac-drbg": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npm.taobao.org/hmac-drbg/download/hmac-drbg-1.0.1.tgz",
+ "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=",
+ "requires": {
+ "hash.js": "^1.0.3",
+ "minimalistic-assert": "^1.0.0",
+ "minimalistic-crypto-utils": "^1.0.1"
+ }
+ },
+ "hosted-git-info": {
+ "version": "2.8.9",
+ "resolved": "https://registry.npm.taobao.org/hosted-git-info/download/hosted-git-info-2.8.9.tgz?cache=0&sync_timestamp=1617826545071&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhosted-git-info%2Fdownload%2Fhosted-git-info-2.8.9.tgz",
+ "integrity": "sha1-3/wL+aIcAiCQkPKqaUKeFBTa8/k="
+ },
+ "hqchart": {
+ "version": "1.1.10351",
+ "resolved": "https://registry.nlark.com/hqchart/download/hqchart-1.1.10351.tgz",
+ "integrity": "sha1-L6n7krWJYK3q7yqD8wP9dNld+5g=",
+ "requires": {
+ "axios": "^0.16.2",
+ "echarts": "^4.8.0",
+ "element-ui": "^1.4.13",
+ "promise-polyfill": "^6.0.2",
+ "qs": "^6.5.0",
+ "vue": "^2.6.9",
+ "vue-plugin-timers": "^0.1.6",
+ "vue-router": "^2.8.1",
+ "webpack": "^3.0"
+ }
+ },
+ "https-browserify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.nlark.com/https-browserify/download/https-browserify-1.0.0.tgz",
+ "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM="
+ },
+ "ieee754": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npm.taobao.org/ieee754/download/ieee754-1.2.1.tgz?cache=0&sync_timestamp=1603838208740&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fieee754%2Fdownload%2Fieee754-1.2.1.tgz",
+ "integrity": "sha1-jrehCmP/8l0VpXsAFYbRd9Gw01I="
+ },
+ "inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npm.taobao.org/inherits/download/inherits-2.0.4.tgz",
+ "integrity": "sha1-D6LGT5MpF8NDOg3tVTY6rjdBa3w="
+ },
+ "interpret": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npm.taobao.org/interpret/download/interpret-1.4.0.tgz",
+ "integrity": "sha1-Zlq4vE2iendKQFhOgS4+D6RbGh4="
+ },
+ "invert-kv": {
+ "version": "1.0.0",
+ "resolved": "https://registry.nlark.com/invert-kv/download/invert-kv-1.0.0.tgz",
+ "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY="
+ },
+ "is-accessor-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npm.taobao.org/is-accessor-descriptor/download/is-accessor-descriptor-0.1.6.tgz",
+ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
+ "optional": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ }
+ },
+ "is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npm.taobao.org/is-arrayish/download/is-arrayish-0.2.1.tgz",
+ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0="
+ },
+ "is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.nlark.com/is-binary-path/download/is-binary-path-2.1.0.tgz",
+ "integrity": "sha1-6h9/O4DwZCNug0cPhsCcJU+0Wwk=",
+ "optional": true,
+ "requires": {
+ "binary-extensions": "^2.0.0"
+ }
+ },
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.nlark.com/is-buffer/download/is-buffer-1.1.6.tgz",
+ "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4="
+ },
+ "is-core-module": {
+ "version": "2.6.0",
+ "resolved": "https://registry.nlark.com/is-core-module/download/is-core-module-2.6.0.tgz?cache=0&sync_timestamp=1629224656971&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fis-core-module%2Fdownload%2Fis-core-module-2.6.0.tgz",
+ "integrity": "sha1-11U7JSb+Wbkro+QMjfdX7Ipwnhk=",
+ "requires": {
+ "has": "^1.0.3"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npm.taobao.org/is-data-descriptor/download/is-data-descriptor-0.1.4.tgz",
+ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
+ "optional": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ }
+ },
+ "is-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npm.taobao.org/is-descriptor/download/is-descriptor-0.1.6.tgz",
+ "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=",
+ "optional": true,
+ "requires": {
+ "is-accessor-descriptor": "^0.1.6",
+ "is-data-descriptor": "^0.1.4",
+ "kind-of": "^5.0.0"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npm.taobao.org/kind-of/download/kind-of-5.1.0.tgz",
+ "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=",
+ "optional": true
+ }
+ }
+ },
+ "is-extendable": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npm.taobao.org/is-extendable/download/is-extendable-0.1.1.tgz",
+ "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
+ "optional": true
+ },
+ "is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npm.taobao.org/is-extglob/download/is-extglob-2.1.1.tgz",
+ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+ "optional": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npm.taobao.org/is-fullwidth-code-point/download/is-fullwidth-code-point-1.0.0.tgz",
+ "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+ "requires": {
+ "number-is-nan": "^1.0.0"
+ }
+ },
+ "is-glob": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npm.taobao.org/is-glob/download/is-glob-4.0.1.tgz",
+ "integrity": "sha1-dWfb6fL14kZ7x3q4PEopSCQHpdw=",
+ "optional": true,
+ "requires": {
+ "is-extglob": "^2.1.1"
+ }
+ },
+ "is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.nlark.com/is-number/download/is-number-7.0.0.tgz",
+ "integrity": "sha1-dTU0W4lnNNX4DE0GxQlVUnoU8Ss=",
+ "optional": true
+ },
+ "is-plain-object": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npm.taobao.org/is-plain-object/download/is-plain-object-2.0.4.tgz",
+ "integrity": "sha1-LBY7P6+xtgbZ0Xko8FwqHDjgdnc=",
+ "optional": true,
+ "requires": {
+ "isobject": "^3.0.1"
+ }
+ },
+ "is-stream": {
+ "version": "1.1.0",
+ "resolved": "https://registry.nlark.com/is-stream/download/is-stream-1.1.0.tgz",
+ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
+ },
+ "is-windows": {
+ "version": "1.0.2",
+ "resolved": "https://registry.nlark.com/is-windows/download/is-windows-1.0.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fis-windows%2Fdownload%2Fis-windows-1.0.2.tgz",
+ "integrity": "sha1-0YUOuXkezRjmGCzhKjDzlmNLsZ0=",
+ "optional": true
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npm.taobao.org/isarray/download/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.nlark.com/isexe/download/isexe-2.0.0.tgz?cache=0&sync_timestamp=1618847054312&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fisexe%2Fdownload%2Fisexe-2.0.0.tgz",
+ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
+ },
+ "isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npm.taobao.org/isobject/download/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+ "optional": true
+ },
+ "jquery": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npm.taobao.org/jquery/download/jquery-3.6.0.tgz",
+ "integrity": "sha1-xyoJ8Vwb3OFC9J2/EXC9+K2sJHA="
+ },
+ "json-loader": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npm.taobao.org/json-loader/download/json-loader-0.5.7.tgz",
+ "integrity": "sha1-3KFKcCNf+C8KyaOr62DTN6NlGF0="
+ },
+ "json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npm.taobao.org/json-schema-traverse/download/json-schema-traverse-0.4.1.tgz?cache=0&sync_timestamp=1607999852153&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjson-schema-traverse%2Fdownload%2Fjson-schema-traverse-0.4.1.tgz",
+ "integrity": "sha1-afaofZUTq4u4/mO9sJecRI5oRmA="
+ },
+ "json5": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npm.taobao.org/json5/download/json5-0.5.1.tgz",
+ "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE="
+ },
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npm.taobao.org/kind-of/download/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ },
+ "lazy-cache": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npm.taobao.org/lazy-cache/download/lazy-cache-1.0.4.tgz",
+ "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4="
+ },
+ "lcid": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npm.taobao.org/lcid/download/lcid-1.0.0.tgz",
+ "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=",
+ "requires": {
+ "invert-kv": "^1.0.0"
+ }
+ },
+ "load-json-file": {
+ "version": "2.0.0",
+ "resolved": "https://registry.nlark.com/load-json-file/download/load-json-file-2.0.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fload-json-file%2Fdownload%2Fload-json-file-2.0.0.tgz",
+ "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=",
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "parse-json": "^2.2.0",
+ "pify": "^2.0.0",
+ "strip-bom": "^3.0.0"
+ }
+ },
+ "loader-runner": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npm.taobao.org/loader-runner/download/loader-runner-2.4.0.tgz?cache=0&sync_timestamp=1610027918622&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Floader-runner%2Fdownload%2Floader-runner-2.4.0.tgz",
+ "integrity": "sha1-7UcGa/5TTX6ExMe5mYwqdWB9k1c="
+ },
+ "loader-utils": {
+ "version": "1.4.0",
+ "resolved": "https://registry.nlark.com/loader-utils/download/loader-utils-1.4.0.tgz",
+ "integrity": "sha1-xXm140yzSxp07cbB+za/o3HVphM=",
+ "requires": {
+ "big.js": "^5.2.2",
+ "emojis-list": "^3.0.0",
+ "json5": "^1.0.1"
+ },
+ "dependencies": {
+ "json5": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npm.taobao.org/json5/download/json5-1.0.1.tgz",
+ "integrity": "sha1-d5+wAYYE+oVOrL9iUhgNg1Q+Pb4=",
+ "requires": {
+ "minimist": "^1.2.0"
+ }
+ }
+ }
+ },
+ "locate-path": {
+ "version": "2.0.0",
+ "resolved": "https://registry.nlark.com/locate-path/download/locate-path-2.0.0.tgz?cache=0&sync_timestamp=1629895618224&other_urls=https%3A%2F%2Fregistry.nlark.com%2Flocate-path%2Fdownload%2Flocate-path-2.0.0.tgz",
+ "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
+ "requires": {
+ "p-locate": "^2.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.nlark.com/lodash/download/lodash-4.17.21.tgz",
+ "integrity": "sha1-Z5WRxWTDv/quhFTPCz3zcMPWkRw="
+ },
+ "longest": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npm.taobao.org/longest/download/longest-1.0.1.tgz",
+ "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc="
+ },
+ "lru-cache": {
+ "version": "4.1.5",
+ "resolved": "https://registry.nlark.com/lru-cache/download/lru-cache-4.1.5.tgz",
+ "integrity": "sha1-i75Q6oW+1ZvJ4z3KuCNe6bz0Q80=",
+ "requires": {
+ "pseudomap": "^1.0.2",
+ "yallist": "^2.1.2"
+ }
+ },
+ "map-cache": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npm.taobao.org/map-cache/download/map-cache-0.2.2.tgz",
+ "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=",
+ "optional": true
+ },
+ "map-visit": {
+ "version": "1.0.0",
+ "resolved": "https://registry.nlark.com/map-visit/download/map-visit-1.0.0.tgz",
+ "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=",
+ "optional": true,
+ "requires": {
+ "object-visit": "^1.0.0"
+ }
+ },
+ "md5.js": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npm.taobao.org/md5.js/download/md5.js-1.3.5.tgz",
+ "integrity": "sha1-tdB7jjIW4+J81yjXL3DR5qNCAF8=",
+ "requires": {
+ "hash-base": "^3.0.0",
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.1.2"
+ }
+ },
+ "mem": {
+ "version": "1.1.0",
+ "resolved": "https://registry.nlark.com/mem/download/mem-1.1.0.tgz?cache=0&sync_timestamp=1626534352883&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fmem%2Fdownload%2Fmem-1.1.0.tgz",
+ "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=",
+ "requires": {
+ "mimic-fn": "^1.0.0"
+ }
+ },
+ "memory-fs": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npm.taobao.org/memory-fs/download/memory-fs-0.4.1.tgz?cache=0&sync_timestamp=1599056143395&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmemory-fs%2Fdownload%2Fmemory-fs-0.4.1.tgz",
+ "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=",
+ "requires": {
+ "errno": "^0.1.3",
+ "readable-stream": "^2.0.1"
+ }
+ },
+ "micromatch": {
+ "version": "3.1.10",
+ "resolved": "https://registry.nlark.com/micromatch/download/micromatch-3.1.10.tgz",
+ "integrity": "sha1-cIWbyVyYQJUvNZoGij/En57PrCM=",
+ "optional": true,
+ "requires": {
+ "arr-diff": "^4.0.0",
+ "array-unique": "^0.3.2",
+ "braces": "^2.3.1",
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "extglob": "^2.0.4",
+ "fragment-cache": "^0.2.1",
+ "kind-of": "^6.0.2",
+ "nanomatch": "^1.2.9",
+ "object.pick": "^1.3.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.2"
+ },
+ "dependencies": {
+ "braces": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npm.taobao.org/braces/download/braces-2.3.2.tgz",
+ "integrity": "sha1-WXn9PxTNUxVl5fot8av/8d+u5yk=",
+ "optional": true,
+ "requires": {
+ "arr-flatten": "^1.1.0",
+ "array-unique": "^0.3.2",
+ "extend-shallow": "^2.0.1",
+ "fill-range": "^4.0.0",
+ "isobject": "^3.0.1",
+ "repeat-element": "^1.1.2",
+ "snapdragon": "^0.8.1",
+ "snapdragon-node": "^2.0.1",
+ "split-string": "^3.0.2",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npm.taobao.org/extend-shallow/download/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "optional": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "fill-range": {
+ "version": "4.0.0",
+ "resolved": "https://registry.nlark.com/fill-range/download/fill-range-4.0.0.tgz",
+ "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
+ "optional": true,
+ "requires": {
+ "extend-shallow": "^2.0.1",
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1",
+ "to-regex-range": "^2.1.0"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npm.taobao.org/extend-shallow/download/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "optional": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "is-number": {
+ "version": "3.0.0",
+ "resolved": "https://registry.nlark.com/is-number/download/is-number-3.0.0.tgz",
+ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+ "optional": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npm.taobao.org/kind-of/download/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "optional": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "kind-of": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npm.taobao.org/kind-of/download/kind-of-6.0.3.tgz",
+ "integrity": "sha1-B8BQNKbDSfoG4k+jWqdttFgM5N0=",
+ "optional": true
+ },
+ "to-regex-range": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npm.taobao.org/to-regex-range/download/to-regex-range-2.1.1.tgz",
+ "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
+ "optional": true,
+ "requires": {
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1"
+ }
+ }
+ }
+ },
+ "miller-rabin": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npm.taobao.org/miller-rabin/download/miller-rabin-4.0.1.tgz",
+ "integrity": "sha1-8IA1HIZbDcViqEYpZtqlNUPHik0=",
+ "requires": {
+ "bn.js": "^4.0.0",
+ "brorand": "^1.0.1"
+ },
+ "dependencies": {
+ "bn.js": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npm.taobao.org/bn.js/download/bn.js-4.12.0.tgz",
+ "integrity": "sha1-d1s/J477uXGO7HNh9IP7Nvu/6og="
+ }
+ }
+ },
+ "mimic-fn": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npm.taobao.org/mimic-fn/download/mimic-fn-1.2.0.tgz",
+ "integrity": "sha1-ggyGo5M0ZA6ZUWkovQP8qIBX0CI="
+ },
+ "minimalistic-assert": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npm.taobao.org/minimalistic-assert/download/minimalistic-assert-1.0.1.tgz",
+ "integrity": "sha1-LhlN4ERibUoQ5/f7wAznPoPk1cc="
+ },
+ "minimalistic-crypto-utils": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npm.taobao.org/minimalistic-crypto-utils/download/minimalistic-crypto-utils-1.0.1.tgz",
+ "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo="
+ },
+ "minimist": {
+ "version": "1.2.5",
+ "resolved": "https://registry.nlark.com/minimist/download/minimist-1.2.5.tgz?cache=0&sync_timestamp=1618846813226&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fminimist%2Fdownload%2Fminimist-1.2.5.tgz",
+ "integrity": "sha1-Z9ZgFLZqaoqqDAg8X9WN9OTpdgI="
+ },
+ "mixin-deep": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npm.taobao.org/mixin-deep/download/mixin-deep-1.3.2.tgz",
+ "integrity": "sha1-ESC0PcNZp4Xc5ltVuC4lfM9HlWY=",
+ "optional": true,
+ "requires": {
+ "for-in": "^1.0.2",
+ "is-extendable": "^1.0.1"
+ },
+ "dependencies": {
+ "is-extendable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npm.taobao.org/is-extendable/download/is-extendable-1.0.1.tgz",
+ "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=",
+ "optional": true,
+ "requires": {
+ "is-plain-object": "^2.0.4"
+ }
+ }
+ }
+ },
+ "mkdirp": {
+ "version": "0.5.5",
+ "resolved": "https://registry.nlark.com/mkdirp/download/mkdirp-0.5.5.tgz?cache=0&sync_timestamp=1624625160603&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fmkdirp%2Fdownload%2Fmkdirp-0.5.5.tgz",
+ "integrity": "sha1-2Rzv1i0UNsoPQWIOJRKI1CAJne8=",
+ "requires": {
+ "minimist": "^1.2.5"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.nlark.com/ms/download/ms-2.0.0.tgz?cache=0&sync_timestamp=1629910562433&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fms%2Fdownload%2Fms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "optional": true
+ },
+ "nan": {
+ "version": "2.15.0",
+ "resolved": "https://registry.nlark.com/nan/download/nan-2.15.0.tgz?cache=0&sync_timestamp=1628093656744&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fnan%2Fdownload%2Fnan-2.15.0.tgz",
+ "integrity": "sha1-PzSkc/8Y4VwbVia2KQO1rW5mX+4=",
+ "optional": true
+ },
+ "nanomatch": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npm.taobao.org/nanomatch/download/nanomatch-1.2.13.tgz",
+ "integrity": "sha1-uHqKpPwN6P5r6IiVs4mD/yZb0Rk=",
+ "optional": true,
+ "requires": {
+ "arr-diff": "^4.0.0",
+ "array-unique": "^0.3.2",
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "fragment-cache": "^0.2.1",
+ "is-windows": "^1.0.2",
+ "kind-of": "^6.0.2",
+ "object.pick": "^1.3.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npm.taobao.org/kind-of/download/kind-of-6.0.3.tgz",
+ "integrity": "sha1-B8BQNKbDSfoG4k+jWqdttFgM5N0=",
+ "optional": true
+ }
+ }
+ },
+ "neo-async": {
+ "version": "2.6.2",
+ "resolved": "https://registry.nlark.com/neo-async/download/neo-async-2.6.2.tgz",
+ "integrity": "sha1-tKr7k+OustgXTKU88WOrfXMIMF8="
+ },
+ "next-tick": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npm.taobao.org/next-tick/download/next-tick-1.0.0.tgz",
+ "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw="
+ },
+ "node-libs-browser": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npm.taobao.org/node-libs-browser/download/node-libs-browser-2.2.1.tgz",
+ "integrity": "sha1-tk9RPRgzhiX5A0bSew0jXmMfZCU=",
+ "requires": {
+ "assert": "^1.1.1",
+ "browserify-zlib": "^0.2.0",
+ "buffer": "^4.3.0",
+ "console-browserify": "^1.1.0",
+ "constants-browserify": "^1.0.0",
+ "crypto-browserify": "^3.11.0",
+ "domain-browser": "^1.1.1",
+ "events": "^3.0.0",
+ "https-browserify": "^1.0.0",
+ "os-browserify": "^0.3.0",
+ "path-browserify": "0.0.1",
+ "process": "^0.11.10",
+ "punycode": "^1.2.4",
+ "querystring-es3": "^0.2.0",
+ "readable-stream": "^2.3.3",
+ "stream-browserify": "^2.0.1",
+ "stream-http": "^2.7.2",
+ "string_decoder": "^1.0.0",
+ "timers-browserify": "^2.0.4",
+ "tty-browserify": "0.0.0",
+ "url": "^0.11.0",
+ "util": "^0.11.0",
+ "vm-browserify": "^1.0.1"
+ },
+ "dependencies": {
+ "punycode": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npm.taobao.org/punycode/download/punycode-1.4.1.tgz",
+ "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
+ }
+ }
+ },
+ "normalize-package-data": {
+ "version": "2.5.0",
+ "resolved": "https://registry.nlark.com/normalize-package-data/download/normalize-package-data-2.5.0.tgz?cache=0&sync_timestamp=1629301911873&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fnormalize-package-data%2Fdownload%2Fnormalize-package-data-2.5.0.tgz",
+ "integrity": "sha1-5m2xg4sgDB38IzIl0SyzZSDiNKg=",
+ "requires": {
+ "hosted-git-info": "^2.1.4",
+ "resolve": "^1.10.0",
+ "semver": "2 || 3 || 4 || 5",
+ "validate-npm-package-license": "^3.0.1"
+ }
+ },
+ "normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npm.taobao.org/normalize-path/download/normalize-path-3.0.0.tgz",
+ "integrity": "sha1-Dc1p/yOhybEf0JeDFmRKA4ghamU=",
+ "optional": true
+ },
+ "npm-run-path": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npm.taobao.org/npm-run-path/download/npm-run-path-2.0.2.tgz",
+ "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
+ "requires": {
+ "path-key": "^2.0.0"
+ }
+ },
+ "number-is-nan": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npm.taobao.org/number-is-nan/download/number-is-nan-1.0.1.tgz?cache=0&sync_timestamp=1617776101309&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnumber-is-nan%2Fdownload%2Fnumber-is-nan-1.0.1.tgz",
+ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npm.taobao.org/object-assign/download/object-assign-4.1.1.tgz",
+ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
+ },
+ "object-copy": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npm.taobao.org/object-copy/download/object-copy-0.1.0.tgz",
+ "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=",
+ "optional": true,
+ "requires": {
+ "copy-descriptor": "^0.1.0",
+ "define-property": "^0.2.5",
+ "kind-of": "^3.0.3"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "optional": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ }
+ }
+ },
+ "object-inspect": {
+ "version": "1.11.0",
+ "resolved": "https://registry.nlark.com/object-inspect/download/object-inspect-1.11.0.tgz?cache=0&sync_timestamp=1626120241132&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fobject-inspect%2Fdownload%2Fobject-inspect-1.11.0.tgz",
+ "integrity": "sha1-nc6xRs7dQUig2eUauI00z1CZIrE="
+ },
+ "object-visit": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npm.taobao.org/object-visit/download/object-visit-1.0.1.tgz",
+ "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=",
+ "optional": true,
+ "requires": {
+ "isobject": "^3.0.0"
+ }
+ },
+ "object.pick": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npm.taobao.org/object.pick/download/object.pick-1.3.0.tgz",
+ "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=",
+ "optional": true,
+ "requires": {
+ "isobject": "^3.0.1"
+ }
+ },
+ "os-browserify": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npm.taobao.org/os-browserify/download/os-browserify-0.3.0.tgz",
+ "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc="
+ },
+ "os-locale": {
+ "version": "2.1.0",
+ "resolved": "https://registry.nlark.com/os-locale/download/os-locale-2.1.0.tgz?cache=0&sync_timestamp=1627564416279&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fos-locale%2Fdownload%2Fos-locale-2.1.0.tgz",
+ "integrity": "sha1-QrwpAKa1uL0XN2yOiCtlr8zyS/I=",
+ "requires": {
+ "execa": "^0.7.0",
+ "lcid": "^1.0.0",
+ "mem": "^1.1.0"
+ }
+ },
+ "p-finally": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npm.taobao.org/p-finally/download/p-finally-1.0.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fp-finally%2Fdownload%2Fp-finally-1.0.0.tgz",
+ "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4="
+ },
+ "p-limit": {
+ "version": "1.3.0",
+ "resolved": "https://registry.nlark.com/p-limit/download/p-limit-1.3.0.tgz",
+ "integrity": "sha1-uGvV8MJWkJEcdZD8v8IBDVSzzLg=",
+ "requires": {
+ "p-try": "^1.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "2.0.0",
+ "resolved": "https://registry.nlark.com/p-locate/download/p-locate-2.0.0.tgz?cache=0&sync_timestamp=1629892721671&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fp-locate%2Fdownload%2Fp-locate-2.0.0.tgz",
+ "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
+ "requires": {
+ "p-limit": "^1.1.0"
+ }
+ },
+ "p-try": {
+ "version": "1.0.0",
+ "resolved": "https://registry.nlark.com/p-try/download/p-try-1.0.0.tgz",
+ "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M="
+ },
+ "pako": {
+ "version": "1.0.11",
+ "resolved": "https://registry.nlark.com/pako/download/pako-1.0.11.tgz?cache=0&sync_timestamp=1627560125189&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpako%2Fdownload%2Fpako-1.0.11.tgz",
+ "integrity": "sha1-bJWZ00DVTf05RjgCUqNXBaa5kr8="
+ },
+ "parse-asn1": {
+ "version": "5.1.6",
+ "resolved": "https://registry.npm.taobao.org/parse-asn1/download/parse-asn1-5.1.6.tgz",
+ "integrity": "sha1-OFCAo+wTy2KmLTlAnLPoiETNrtQ=",
+ "requires": {
+ "asn1.js": "^5.2.0",
+ "browserify-aes": "^1.0.0",
+ "evp_bytestokey": "^1.0.0",
+ "pbkdf2": "^3.0.3",
+ "safe-buffer": "^5.1.1"
+ }
+ },
+ "parse-json": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npm.taobao.org/parse-json/download/parse-json-2.2.0.tgz?cache=0&sync_timestamp=1610966709037&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fparse-json%2Fdownload%2Fparse-json-2.2.0.tgz",
+ "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
+ "requires": {
+ "error-ex": "^1.2.0"
+ }
+ },
+ "pascalcase": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npm.taobao.org/pascalcase/download/pascalcase-0.1.1.tgz",
+ "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=",
+ "optional": true
+ },
+ "path-browserify": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npm.taobao.org/path-browserify/download/path-browserify-0.0.1.tgz",
+ "integrity": "sha1-5sTd1+06onxoogzE5Q4aTug7vEo="
+ },
+ "path-dirname": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npm.taobao.org/path-dirname/download/path-dirname-1.0.2.tgz",
+ "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=",
+ "optional": true
+ },
+ "path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.nlark.com/path-exists/download/path-exists-3.0.0.tgz",
+ "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU="
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npm.taobao.org/path-is-absolute/download/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+ "optional": true
+ },
+ "path-key": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npm.taobao.org/path-key/download/path-key-2.0.1.tgz?cache=0&sync_timestamp=1617971695678&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpath-key%2Fdownload%2Fpath-key-2.0.1.tgz",
+ "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A="
+ },
+ "path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.nlark.com/path-parse/download/path-parse-1.0.7.tgz",
+ "integrity": "sha1-+8EUtgykKzDZ2vWFjkvWi77bZzU="
+ },
+ "path-type": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npm.taobao.org/path-type/download/path-type-2.0.0.tgz?cache=0&sync_timestamp=1611752058913&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpath-type%2Fdownload%2Fpath-type-2.0.0.tgz",
+ "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=",
+ "requires": {
+ "pify": "^2.0.0"
+ }
+ },
+ "pbkdf2": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npm.taobao.org/pbkdf2/download/pbkdf2-3.1.2.tgz?cache=0&sync_timestamp=1617975984684&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpbkdf2%2Fdownload%2Fpbkdf2-3.1.2.tgz",
+ "integrity": "sha1-3YIqoIh1gOUvGgOdw+2hCO+uMHU=",
+ "requires": {
+ "create-hash": "^1.1.2",
+ "create-hmac": "^1.1.4",
+ "ripemd160": "^2.0.1",
+ "safe-buffer": "^5.0.1",
+ "sha.js": "^2.4.8"
+ }
+ },
+ "picomatch": {
+ "version": "2.3.0",
+ "resolved": "https://registry.nlark.com/picomatch/download/picomatch-2.3.0.tgz?cache=0&sync_timestamp=1621648246651&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpicomatch%2Fdownload%2Fpicomatch-2.3.0.tgz",
+ "integrity": "sha1-8fBh3o9qS/AiiS4tEoI0+5gwKXI=",
+ "optional": true
+ },
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npm.taobao.org/pify/download/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw="
+ },
+ "posix-character-classes": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npm.taobao.org/posix-character-classes/download/posix-character-classes-0.1.1.tgz",
+ "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=",
+ "optional": true
+ },
+ "process": {
+ "version": "0.11.10",
+ "resolved": "https://registry.npm.taobao.org/process/download/process-0.11.10.tgz",
+ "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI="
+ },
+ "process-nextick-args": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npm.taobao.org/process-nextick-args/download/process-nextick-args-2.0.1.tgz",
+ "integrity": "sha1-eCDZsWEgzFXKmud5JoCufbptf+I="
+ },
+ "promise-polyfill": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npm.taobao.org/promise-polyfill/download/promise-polyfill-6.1.0.tgz",
+ "integrity": "sha1-36lpQ+qcEh/KTem1hoyznTRy4Fc="
+ },
+ "prr": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npm.taobao.org/prr/download/prr-1.0.1.tgz",
+ "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY="
+ },
+ "pseudomap": {
+ "version": "1.0.2",
+ "resolved": "https://registry.nlark.com/pseudomap/download/pseudomap-1.0.2.tgz",
+ "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
+ },
+ "public-encrypt": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npm.taobao.org/public-encrypt/download/public-encrypt-4.0.3.tgz",
+ "integrity": "sha1-T8ydd6B+SLp1J+fL4N4z0HATMeA=",
+ "requires": {
+ "bn.js": "^4.1.0",
+ "browserify-rsa": "^4.0.0",
+ "create-hash": "^1.1.0",
+ "parse-asn1": "^5.0.0",
+ "randombytes": "^2.0.1",
+ "safe-buffer": "^5.1.2"
+ },
+ "dependencies": {
+ "bn.js": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npm.taobao.org/bn.js/download/bn.js-4.12.0.tgz",
+ "integrity": "sha1-d1s/J477uXGO7HNh9IP7Nvu/6og="
+ }
+ }
+ },
+ "punycode": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npm.taobao.org/punycode/download/punycode-2.1.1.tgz",
+ "integrity": "sha1-tYsBCsQMIsVldhbI0sLALHv0eew="
+ },
+ "qs": {
+ "version": "6.10.1",
+ "resolved": "https://registry.nlark.com/qs/download/qs-6.10.1.tgz",
+ "integrity": "sha1-STFIL6jWR6Wqt5nFJx0hM7mB+2o=",
+ "requires": {
+ "side-channel": "^1.0.4"
+ }
+ },
+ "querystring": {
+ "version": "0.2.0",
+ "resolved": "https://registry.nlark.com/querystring/download/querystring-0.2.0.tgz?cache=0&sync_timestamp=1626179435543&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fquerystring%2Fdownload%2Fquerystring-0.2.0.tgz",
+ "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA="
+ },
+ "querystring-es3": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npm.taobao.org/querystring-es3/download/querystring-es3-0.2.1.tgz",
+ "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM="
+ },
+ "randombytes": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npm.taobao.org/randombytes/download/randombytes-2.1.0.tgz",
+ "integrity": "sha1-32+ENy8CcNxlzfYpE0mrekc9Tyo=",
+ "requires": {
+ "safe-buffer": "^5.1.0"
+ }
+ },
+ "randomfill": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npm.taobao.org/randomfill/download/randomfill-1.0.4.tgz",
+ "integrity": "sha1-ySGW/IarQr6YPxvzF3giSTHWFFg=",
+ "requires": {
+ "randombytes": "^2.0.5",
+ "safe-buffer": "^5.1.0"
+ }
+ },
+ "read-pkg": {
+ "version": "2.0.0",
+ "resolved": "https://registry.nlark.com/read-pkg/download/read-pkg-2.0.0.tgz",
+ "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=",
+ "requires": {
+ "load-json-file": "^2.0.0",
+ "normalize-package-data": "^2.3.2",
+ "path-type": "^2.0.0"
+ }
+ },
+ "read-pkg-up": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npm.taobao.org/read-pkg-up/download/read-pkg-up-2.0.0.tgz",
+ "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=",
+ "requires": {
+ "find-up": "^2.0.0",
+ "read-pkg": "^2.0.0"
+ }
+ },
+ "readable-stream": {
+ "version": "2.3.7",
+ "resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.7.tgz",
+ "integrity": "sha1-Hsoc9xGu+BTAT2IlKjamL2yyO1c=",
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "readdirp": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npm.taobao.org/readdirp/download/readdirp-3.6.0.tgz?cache=0&sync_timestamp=1615717369278&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Freaddirp%2Fdownload%2Freaddirp-3.6.0.tgz",
+ "integrity": "sha1-dKNwvYVxFuJFspzJc0DNQxoCpsc=",
+ "optional": true,
+ "requires": {
+ "picomatch": "^2.2.1"
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.11.1",
+ "resolved": "https://registry.nlark.com/regenerator-runtime/download/regenerator-runtime-0.11.1.tgz?cache=0&sync_timestamp=1626993001371&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fregenerator-runtime%2Fdownload%2Fregenerator-runtime-0.11.1.tgz",
+ "integrity": "sha1-vgWtf5v30i4Fb5cmzuUBf78Z4uk="
+ },
+ "regex-not": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npm.taobao.org/regex-not/download/regex-not-1.0.2.tgz",
+ "integrity": "sha1-H07OJ+ALC2XgJHpoEOaoXYOldSw=",
+ "optional": true,
+ "requires": {
+ "extend-shallow": "^3.0.2",
+ "safe-regex": "^1.1.0"
+ }
+ },
+ "remove-trailing-separator": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npm.taobao.org/remove-trailing-separator/download/remove-trailing-separator-1.1.0.tgz",
+ "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=",
+ "optional": true
+ },
+ "repeat-element": {
+ "version": "1.1.4",
+ "resolved": "https://registry.nlark.com/repeat-element/download/repeat-element-1.1.4.tgz",
+ "integrity": "sha1-vmgVIIR6tYx1aKx1+/rSjtQtOek=",
+ "optional": true
+ },
+ "repeat-string": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npm.taobao.org/repeat-string/download/repeat-string-1.6.1.tgz",
+ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc="
+ },
+ "require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.nlark.com/require-directory/download/require-directory-2.1.1.tgz",
+ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="
+ },
+ "require-main-filename": {
+ "version": "1.0.1",
+ "resolved": "https://registry.nlark.com/require-main-filename/download/require-main-filename-1.0.1.tgz",
+ "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE="
+ },
+ "resolve": {
+ "version": "1.20.0",
+ "resolved": "https://registry.nlark.com/resolve/download/resolve-1.20.0.tgz",
+ "integrity": "sha1-YpoBP7P3B1XW8LeTXMHCxTeLGXU=",
+ "requires": {
+ "is-core-module": "^2.2.0",
+ "path-parse": "^1.0.6"
+ }
+ },
+ "resolve-url": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npm.taobao.org/resolve-url/download/resolve-url-0.2.1.tgz",
+ "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=",
+ "optional": true
+ },
+ "ret": {
+ "version": "0.1.15",
+ "resolved": "https://registry.npm.taobao.org/ret/download/ret-0.1.15.tgz",
+ "integrity": "sha1-uKSCXVvbH8P29Twrwz+BOIaBx7w=",
+ "optional": true
+ },
+ "right-align": {
+ "version": "0.1.3",
+ "resolved": "https://registry.nlark.com/right-align/download/right-align-0.1.3.tgz",
+ "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=",
+ "requires": {
+ "align-text": "^0.1.1"
+ }
+ },
+ "ripemd160": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npm.taobao.org/ripemd160/download/ripemd160-2.0.2.tgz",
+ "integrity": "sha1-ocGm9iR1FXe6XQeRTLyShQWFiQw=",
+ "requires": {
+ "hash-base": "^3.0.0",
+ "inherits": "^2.0.1"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.1.2.tgz",
+ "integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0="
+ },
+ "safe-regex": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npm.taobao.org/safe-regex/download/safe-regex-1.1.0.tgz",
+ "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
+ "optional": true,
+ "requires": {
+ "ret": "~0.1.10"
+ }
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npm.taobao.org/safer-buffer/download/safer-buffer-2.1.2.tgz",
+ "integrity": "sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo="
+ },
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npm.taobao.org/semver/download/semver-5.7.1.tgz",
+ "integrity": "sha1-qVT5Ma66UI0we78Gnv8MAclhFvc="
+ },
+ "set-blocking": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npm.taobao.org/set-blocking/download/set-blocking-2.0.0.tgz",
+ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
+ },
+ "set-value": {
+ "version": "2.0.1",
+ "resolved": "https://registry.nlark.com/set-value/download/set-value-2.0.1.tgz",
+ "integrity": "sha1-oY1AUw5vB95CKMfe/kInr4ytAFs=",
+ "optional": true,
+ "requires": {
+ "extend-shallow": "^2.0.1",
+ "is-extendable": "^0.1.1",
+ "is-plain-object": "^2.0.3",
+ "split-string": "^3.0.1"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npm.taobao.org/extend-shallow/download/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "optional": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "setimmediate": {
+ "version": "1.0.5",
+ "resolved": "https://registry.nlark.com/setimmediate/download/setimmediate-1.0.5.tgz",
+ "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU="
+ },
+ "sha.js": {
+ "version": "2.4.11",
+ "resolved": "https://registry.npm.taobao.org/sha.js/download/sha.js-2.4.11.tgz",
+ "integrity": "sha1-N6XPC4HsvGlD3hCbopYNGyZYSuc=",
+ "requires": {
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "shebang-command": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npm.taobao.org/shebang-command/download/shebang-command-1.2.0.tgz",
+ "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
+ "requires": {
+ "shebang-regex": "^1.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.nlark.com/shebang-regex/download/shebang-regex-1.0.0.tgz?cache=0&sync_timestamp=1628896299850&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fshebang-regex%2Fdownload%2Fshebang-regex-1.0.0.tgz",
+ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM="
+ },
+ "side-channel": {
+ "version": "1.0.4",
+ "resolved": "https://registry.nlark.com/side-channel/download/side-channel-1.0.4.tgz",
+ "integrity": "sha1-785cj9wQTudRslxY1CkAEfpeos8=",
+ "requires": {
+ "call-bind": "^1.0.0",
+ "get-intrinsic": "^1.0.2",
+ "object-inspect": "^1.9.0"
+ }
+ },
+ "signal-exit": {
+ "version": "3.0.3",
+ "resolved": "https://registry.nlark.com/signal-exit/download/signal-exit-3.0.3.tgz",
+ "integrity": "sha1-oUEMLt2PB3sItOJTyOrPyvBXRhw="
+ },
+ "snapdragon": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npm.taobao.org/snapdragon/download/snapdragon-0.8.2.tgz",
+ "integrity": "sha1-ZJIufFZbDhQgS6GqfWlkJ40lGC0=",
+ "optional": true,
+ "requires": {
+ "base": "^0.11.1",
+ "debug": "^2.2.0",
+ "define-property": "^0.2.5",
+ "extend-shallow": "^2.0.1",
+ "map-cache": "^0.2.2",
+ "source-map": "^0.5.6",
+ "source-map-resolve": "^0.5.0",
+ "use": "^3.1.0"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "optional": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npm.taobao.org/extend-shallow/download/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "optional": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "snapdragon-node": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npm.taobao.org/snapdragon-node/download/snapdragon-node-2.1.1.tgz",
+ "integrity": "sha1-bBdfhv8UvbByRWPo88GwIaKGhTs=",
+ "optional": true,
+ "requires": {
+ "define-property": "^1.0.0",
+ "isobject": "^3.0.0",
+ "snapdragon-util": "^3.0.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "optional": true,
+ "requires": {
+ "is-descriptor": "^1.0.0"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npm.taobao.org/is-accessor-descriptor/download/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=",
+ "optional": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npm.taobao.org/is-data-descriptor/download/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=",
+ "optional": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npm.taobao.org/is-descriptor/download/is-descriptor-1.0.2.tgz",
+ "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=",
+ "optional": true,
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ },
+ "kind-of": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npm.taobao.org/kind-of/download/kind-of-6.0.3.tgz",
+ "integrity": "sha1-B8BQNKbDSfoG4k+jWqdttFgM5N0=",
+ "optional": true
+ }
+ }
+ },
+ "snapdragon-util": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npm.taobao.org/snapdragon-util/download/snapdragon-util-3.0.1.tgz",
+ "integrity": "sha1-+VZHlIbyrNeXAGk/b3uAXkWrVuI=",
+ "optional": true,
+ "requires": {
+ "kind-of": "^3.2.0"
+ }
+ },
+ "source-list-map": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npm.taobao.org/source-list-map/download/source-list-map-2.0.1.tgz",
+ "integrity": "sha1-OZO9hzv8SEecyp6jpUeDXHwVSzQ="
+ },
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
+ },
+ "source-map-resolve": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npm.taobao.org/source-map-resolve/download/source-map-resolve-0.5.3.tgz",
+ "integrity": "sha1-GQhmvs51U+H48mei7oLGBrVQmho=",
+ "optional": true,
+ "requires": {
+ "atob": "^2.1.2",
+ "decode-uri-component": "^0.2.0",
+ "resolve-url": "^0.2.1",
+ "source-map-url": "^0.4.0",
+ "urix": "^0.1.0"
+ }
+ },
+ "source-map-url": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npm.taobao.org/source-map-url/download/source-map-url-0.4.1.tgz",
+ "integrity": "sha1-CvZmBadFpaL5HPG7+KevvCg97FY=",
+ "optional": true
+ },
+ "spdx-correct": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npm.taobao.org/spdx-correct/download/spdx-correct-3.1.1.tgz",
+ "integrity": "sha1-3s6BrJweZxPl99G28X1Gj6U9iak=",
+ "requires": {
+ "spdx-expression-parse": "^3.0.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "spdx-exceptions": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npm.taobao.org/spdx-exceptions/download/spdx-exceptions-2.3.0.tgz",
+ "integrity": "sha1-PyjOGnegA3JoPq3kpDMYNSeiFj0="
+ },
+ "spdx-expression-parse": {
+ "version": "3.0.1",
+ "resolved": "https://registry.nlark.com/spdx-expression-parse/download/spdx-expression-parse-3.0.1.tgz",
+ "integrity": "sha1-z3D1BILu/cmOPOCmgz5KU87rpnk=",
+ "requires": {
+ "spdx-exceptions": "^2.1.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "spdx-license-ids": {
+ "version": "3.0.10",
+ "resolved": "https://registry.nlark.com/spdx-license-ids/download/spdx-license-ids-3.0.10.tgz",
+ "integrity": "sha1-DZvszN5wA9bGWNSH3UijLwvzAUs="
+ },
+ "split-string": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npm.taobao.org/split-string/download/split-string-3.1.0.tgz",
+ "integrity": "sha1-fLCd2jqGWFcFxks5pkZgOGguj+I=",
+ "optional": true,
+ "requires": {
+ "extend-shallow": "^3.0.0"
+ }
+ },
+ "static-extend": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npm.taobao.org/static-extend/download/static-extend-0.1.2.tgz",
+ "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=",
+ "optional": true,
+ "requires": {
+ "define-property": "^0.2.5",
+ "object-copy": "^0.1.0"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npm.taobao.org/define-property/download/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "optional": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ }
+ }
+ },
+ "stream-browserify": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npm.taobao.org/stream-browserify/download/stream-browserify-2.0.2.tgz",
+ "integrity": "sha1-h1IdOKRKp+6RzhzSpH3wy0ndZgs=",
+ "requires": {
+ "inherits": "~2.0.1",
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "stream-http": {
+ "version": "2.8.3",
+ "resolved": "https://registry.npm.taobao.org/stream-http/download/stream-http-2.8.3.tgz",
+ "integrity": "sha1-stJCRpKIpaJ+xP6JM6z2I95lFPw=",
+ "requires": {
+ "builtin-status-codes": "^3.0.0",
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.3.6",
+ "to-arraybuffer": "^1.0.0",
+ "xtend": "^4.0.0"
+ }
+ },
+ "string-width": {
+ "version": "2.1.1",
+ "resolved": "https://registry.nlark.com/string-width/download/string-width-2.1.1.tgz",
+ "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=",
+ "requires": {
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^4.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.nlark.com/ansi-regex/download/ansi-regex-3.0.0.tgz?cache=0&sync_timestamp=1631634988487&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fansi-regex%2Fdownload%2Fansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="
+ },
+ "is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npm.taobao.org/is-fullwidth-code-point/download/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
+ },
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.nlark.com/strip-ansi/download/strip-ansi-4.0.0.tgz?cache=0&sync_timestamp=1631350330859&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fstrip-ansi%2Fdownload%2Fstrip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "requires": {
+ "ansi-regex": "^3.0.0"
+ }
+ }
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.nlark.com/string_decoder/download/string_decoder-1.1.1.tgz",
+ "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=",
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.nlark.com/strip-ansi/download/strip-ansi-3.0.1.tgz?cache=0&sync_timestamp=1631350330859&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fstrip-ansi%2Fdownload%2Fstrip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ },
+ "strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.nlark.com/strip-bom/download/strip-bom-3.0.0.tgz",
+ "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM="
+ },
+ "strip-eof": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npm.taobao.org/strip-eof/download/strip-eof-1.0.0.tgz",
+ "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8="
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.nlark.com/supports-color/download/supports-color-4.5.0.tgz?cache=0&sync_timestamp=1626703414084&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fsupports-color%2Fdownload%2Fsupports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "requires": {
+ "has-flag": "^2.0.0"
+ }
+ },
+ "tapable": {
+ "version": "0.2.9",
+ "resolved": "https://registry.nlark.com/tapable/download/tapable-0.2.9.tgz?cache=0&sync_timestamp=1631526982870&other_urls=https%3A%2F%2Fregistry.nlark.com%2Ftapable%2Fdownload%2Ftapable-0.2.9.tgz",
+ "integrity": "sha1-ry2LvJsE907hevK02QSPgHrNGKg="
+ },
+ "throttle-debounce": {
+ "version": "1.1.0",
+ "resolved": "https://registry.nlark.com/throttle-debounce/download/throttle-debounce-1.1.0.tgz",
+ "integrity": "sha1-UYU9o3vmihVctugns1FKPEIuic0="
+ },
+ "timers-browserify": {
+ "version": "2.0.12",
+ "resolved": "https://registry.npm.taobao.org/timers-browserify/download/timers-browserify-2.0.12.tgz?cache=0&sync_timestamp=1603793741116&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftimers-browserify%2Fdownload%2Ftimers-browserify-2.0.12.tgz",
+ "integrity": "sha1-RKRcEfv0B/NPl7zNFXfGUjYbAO4=",
+ "requires": {
+ "setimmediate": "^1.0.4"
+ }
+ },
+ "to-arraybuffer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npm.taobao.org/to-arraybuffer/download/to-arraybuffer-1.0.1.tgz",
+ "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M="
+ },
+ "to-object-path": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npm.taobao.org/to-object-path/download/to-object-path-0.3.0.tgz",
+ "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=",
+ "optional": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ }
+ },
+ "to-regex": {
+ "version": "3.0.2",
+ "resolved": "https://registry.nlark.com/to-regex/download/to-regex-3.0.2.tgz",
+ "integrity": "sha1-E8/dmzNlUvMLUfM6iuG0Knp1mc4=",
+ "optional": true,
+ "requires": {
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "regex-not": "^1.0.2",
+ "safe-regex": "^1.1.0"
+ }
+ },
+ "to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npm.taobao.org/to-regex-range/download/to-regex-range-5.0.1.tgz",
+ "integrity": "sha1-FkjESq58jZiKMmAY7XL1tN0DkuQ=",
+ "optional": true,
+ "requires": {
+ "is-number": "^7.0.0"
+ }
+ },
+ "tty-browserify": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npm.taobao.org/tty-browserify/download/tty-browserify-0.0.0.tgz",
+ "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY="
+ },
+ "type": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npm.taobao.org/type/download/type-1.2.0.tgz",
+ "integrity": "sha1-hI3XaY2vo+VKbEeedZxLw/GIR6A="
+ },
+ "uglify-js": {
+ "version": "2.8.29",
+ "resolved": "https://registry.nlark.com/uglify-js/download/uglify-js-2.8.29.tgz?cache=0&sync_timestamp=1631026519465&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fuglify-js%2Fdownload%2Fuglify-js-2.8.29.tgz",
+ "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=",
+ "requires": {
+ "source-map": "~0.5.1",
+ "uglify-to-browserify": "~1.0.0",
+ "yargs": "~3.10.0"
+ },
+ "dependencies": {
+ "yargs": {
+ "version": "3.10.0",
+ "resolved": "https://registry.nlark.com/yargs/download/yargs-3.10.0.tgz",
+ "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=",
+ "requires": {
+ "camelcase": "^1.0.2",
+ "cliui": "^2.1.0",
+ "decamelize": "^1.0.0",
+ "window-size": "0.1.0"
+ }
+ }
+ }
+ },
+ "uglify-to-browserify": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npm.taobao.org/uglify-to-browserify/download/uglify-to-browserify-1.0.2.tgz",
+ "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=",
+ "optional": true
+ },
+ "uglifyjs-webpack-plugin": {
+ "version": "0.4.6",
+ "resolved": "https://registry.nlark.com/uglifyjs-webpack-plugin/download/uglifyjs-webpack-plugin-0.4.6.tgz",
+ "integrity": "sha1-uVH0q7a9YX5m9j64kUmOORdj4wk=",
+ "requires": {
+ "source-map": "^0.5.6",
+ "uglify-js": "^2.8.29",
+ "webpack-sources": "^1.0.1"
+ }
+ },
+ "union-value": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npm.taobao.org/union-value/download/union-value-1.0.1.tgz",
+ "integrity": "sha1-C2/nuDWuzaYcbqTU8CwUIh4QmEc=",
+ "optional": true,
+ "requires": {
+ "arr-union": "^3.1.0",
+ "get-value": "^2.0.6",
+ "is-extendable": "^0.1.1",
+ "set-value": "^2.0.1"
+ }
+ },
+ "unset-value": {
+ "version": "1.0.0",
+ "resolved": "https://registry.nlark.com/unset-value/download/unset-value-1.0.0.tgz",
+ "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=",
+ "optional": true,
+ "requires": {
+ "has-value": "^0.3.1",
+ "isobject": "^3.0.0"
+ },
+ "dependencies": {
+ "has-value": {
+ "version": "0.3.1",
+ "resolved": "https://registry.nlark.com/has-value/download/has-value-0.3.1.tgz",
+ "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=",
+ "optional": true,
+ "requires": {
+ "get-value": "^2.0.3",
+ "has-values": "^0.1.4",
+ "isobject": "^2.0.0"
+ },
+ "dependencies": {
+ "isobject": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npm.taobao.org/isobject/download/isobject-2.1.0.tgz",
+ "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
+ "optional": true,
+ "requires": {
+ "isarray": "1.0.0"
+ }
+ }
+ }
+ },
+ "has-values": {
+ "version": "0.1.4",
+ "resolved": "https://registry.nlark.com/has-values/download/has-values-0.1.4.tgz",
+ "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=",
+ "optional": true
+ }
+ }
+ },
+ "upath": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npm.taobao.org/upath/download/upath-1.2.0.tgz",
+ "integrity": "sha1-j2bbzVWog6za5ECK+LA1pQRMGJQ=",
+ "optional": true
+ },
+ "uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.nlark.com/uri-js/download/uri-js-4.4.1.tgz",
+ "integrity": "sha1-mxpSWVIlhZ5V9mnZKPiMbFfyp34=",
+ "requires": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "urix": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npm.taobao.org/urix/download/urix-0.1.0.tgz",
+ "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=",
+ "optional": true
+ },
+ "url": {
+ "version": "0.11.0",
+ "resolved": "https://registry.nlark.com/url/download/url-0.11.0.tgz",
+ "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=",
+ "requires": {
+ "punycode": "1.3.2",
+ "querystring": "0.2.0"
+ },
+ "dependencies": {
+ "punycode": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npm.taobao.org/punycode/download/punycode-1.3.2.tgz",
+ "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0="
+ }
+ }
+ },
+ "use": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npm.taobao.org/use/download/use-3.1.1.tgz",
+ "integrity": "sha1-1QyMrHmhn7wg8pEfVuuXP04QBw8=",
+ "optional": true
+ },
+ "util": {
+ "version": "0.11.1",
+ "resolved": "https://registry.nlark.com/util/download/util-0.11.1.tgz?cache=0&sync_timestamp=1622212984161&other_urls=https%3A%2F%2Fregistry.nlark.com%2Futil%2Fdownload%2Futil-0.11.1.tgz",
+ "integrity": "sha1-MjZzNyDsZLsn9uJvQhqqLhtYjWE=",
+ "requires": {
+ "inherits": "2.0.3"
+ },
+ "dependencies": {
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npm.taobao.org/inherits/download/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+ }
+ }
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npm.taobao.org/util-deprecate/download/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
+ },
+ "validate-npm-package-license": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npm.taobao.org/validate-npm-package-license/download/validate-npm-package-license-3.0.4.tgz",
+ "integrity": "sha1-/JH2uce6FchX9MssXe/uw51PQQo=",
+ "requires": {
+ "spdx-correct": "^3.0.0",
+ "spdx-expression-parse": "^3.0.0"
+ }
+ },
+ "vm-browserify": {
+ "version": "1.1.2",
+ "resolved": "https://registry.nlark.com/vm-browserify/download/vm-browserify-1.1.2.tgz?cache=0&sync_timestamp=1624521940875&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fvm-browserify%2Fdownload%2Fvm-browserify-1.1.2.tgz",
+ "integrity": "sha1-eGQcSIuObKkadfUR56OzKobl3aA="
+ },
+ "vue": {
+ "version": "2.6.14",
+ "resolved": "https://registry.nlark.com/vue/download/vue-2.6.14.tgz?cache=0&sync_timestamp=1631141991995&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fvue%2Fdownload%2Fvue-2.6.14.tgz",
+ "integrity": "sha1-5RqlJQJQ1Wmj+606ilpofWA24jU="
+ },
+ "vue-plugin-timers": {
+ "version": "0.1.6",
+ "resolved": "https://registry.nlark.com/vue-plugin-timers/download/vue-plugin-timers-0.1.6.tgz",
+ "integrity": "sha1-6INTdzOxzUmgsadXoLJXtM2H51s="
+ },
+ "vue-router": {
+ "version": "2.8.1",
+ "resolved": "https://registry.nlark.com/vue-router/download/vue-router-2.8.1.tgz?cache=0&sync_timestamp=1628495505697&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fvue-router%2Fdownload%2Fvue-router-2.8.1.tgz",
+ "integrity": "sha1-mDPJ7lesg76wJpBW/v7nFxPyBpU="
+ },
+ "watchpack": {
+ "version": "1.7.5",
+ "resolved": "https://registry.nlark.com/watchpack/download/watchpack-1.7.5.tgz?cache=0&sync_timestamp=1621437868630&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fwatchpack%2Fdownload%2Fwatchpack-1.7.5.tgz",
+ "integrity": "sha1-EmfmxV4Lm1vkTCAjrtVDeiwmxFM=",
+ "requires": {
+ "chokidar": "^3.4.1",
+ "graceful-fs": "^4.1.2",
+ "neo-async": "^2.5.0",
+ "watchpack-chokidar2": "^2.0.1"
+ }
+ },
+ "watchpack-chokidar2": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npm.taobao.org/watchpack-chokidar2/download/watchpack-chokidar2-2.0.1.tgz",
+ "integrity": "sha1-OFAAcu5uzmbzdpk2lQ6hdxvhyVc=",
+ "optional": true,
+ "requires": {
+ "chokidar": "^2.1.8"
+ },
+ "dependencies": {
+ "anymatch": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npm.taobao.org/anymatch/download/anymatch-2.0.0.tgz",
+ "integrity": "sha1-vLJLTzeTTZqnrBe0ra+J58du8us=",
+ "optional": true,
+ "requires": {
+ "micromatch": "^3.1.4",
+ "normalize-path": "^2.1.1"
+ },
+ "dependencies": {
+ "normalize-path": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npm.taobao.org/normalize-path/download/normalize-path-2.1.1.tgz",
+ "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
+ "optional": true,
+ "requires": {
+ "remove-trailing-separator": "^1.0.1"
+ }
+ }
+ }
+ },
+ "binary-extensions": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npm.taobao.org/binary-extensions/download/binary-extensions-1.13.1.tgz?cache=0&sync_timestamp=1610299308660&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbinary-extensions%2Fdownload%2Fbinary-extensions-1.13.1.tgz",
+ "integrity": "sha1-WYr+VHVbKGilMw0q/51Ou1Mgm2U=",
+ "optional": true
+ },
+ "braces": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npm.taobao.org/braces/download/braces-2.3.2.tgz",
+ "integrity": "sha1-WXn9PxTNUxVl5fot8av/8d+u5yk=",
+ "optional": true,
+ "requires": {
+ "arr-flatten": "^1.1.0",
+ "array-unique": "^0.3.2",
+ "extend-shallow": "^2.0.1",
+ "fill-range": "^4.0.0",
+ "isobject": "^3.0.1",
+ "repeat-element": "^1.1.2",
+ "snapdragon": "^0.8.1",
+ "snapdragon-node": "^2.0.1",
+ "split-string": "^3.0.2",
+ "to-regex": "^3.0.1"
+ }
+ },
+ "chokidar": {
+ "version": "2.1.8",
+ "resolved": "https://registry.nlark.com/chokidar/download/chokidar-2.1.8.tgz",
+ "integrity": "sha1-gEs6e2qZNYw8XGHnHYco8EHP+Rc=",
+ "optional": true,
+ "requires": {
+ "anymatch": "^2.0.0",
+ "async-each": "^1.0.1",
+ "braces": "^2.3.2",
+ "fsevents": "^1.2.7",
+ "glob-parent": "^3.1.0",
+ "inherits": "^2.0.3",
+ "is-binary-path": "^1.0.0",
+ "is-glob": "^4.0.0",
+ "normalize-path": "^3.0.0",
+ "path-is-absolute": "^1.0.0",
+ "readdirp": "^2.2.1",
+ "upath": "^1.1.1"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npm.taobao.org/extend-shallow/download/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "optional": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ },
+ "fill-range": {
+ "version": "4.0.0",
+ "resolved": "https://registry.nlark.com/fill-range/download/fill-range-4.0.0.tgz",
+ "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
+ "optional": true,
+ "requires": {
+ "extend-shallow": "^2.0.1",
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1",
+ "to-regex-range": "^2.1.0"
+ }
+ },
+ "fsevents": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npm.taobao.org/fsevents/download/fsevents-1.2.13.tgz?cache=0&sync_timestamp=1612536512306&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffsevents%2Fdownload%2Ffsevents-1.2.13.tgz",
+ "integrity": "sha1-8yXLBFVZJCi88Rs4M3DvcOO/zDg=",
+ "optional": true,
+ "requires": {
+ "bindings": "^1.5.0",
+ "nan": "^2.12.1"
+ }
+ },
+ "glob-parent": {
+ "version": "3.1.0",
+ "resolved": "https://registry.nlark.com/glob-parent/download/glob-parent-3.1.0.tgz?cache=0&sync_timestamp=1626760165717&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fglob-parent%2Fdownload%2Fglob-parent-3.1.0.tgz",
+ "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
+ "optional": true,
+ "requires": {
+ "is-glob": "^3.1.0",
+ "path-dirname": "^1.0.0"
+ },
+ "dependencies": {
+ "is-glob": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npm.taobao.org/is-glob/download/is-glob-3.1.0.tgz",
+ "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
+ "optional": true,
+ "requires": {
+ "is-extglob": "^2.1.0"
+ }
+ }
+ }
+ },
+ "is-binary-path": {
+ "version": "1.0.1",
+ "resolved": "https://registry.nlark.com/is-binary-path/download/is-binary-path-1.0.1.tgz",
+ "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
+ "optional": true,
+ "requires": {
+ "binary-extensions": "^1.0.0"
+ }
+ },
+ "is-number": {
+ "version": "3.0.0",
+ "resolved": "https://registry.nlark.com/is-number/download/is-number-3.0.0.tgz",
+ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+ "optional": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ }
+ },
+ "readdirp": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npm.taobao.org/readdirp/download/readdirp-2.2.1.tgz?cache=0&sync_timestamp=1615717369278&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Freaddirp%2Fdownload%2Freaddirp-2.2.1.tgz",
+ "integrity": "sha1-DodiKjMlqjPokihcr4tOhGUppSU=",
+ "optional": true,
+ "requires": {
+ "graceful-fs": "^4.1.11",
+ "micromatch": "^3.1.10",
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "to-regex-range": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npm.taobao.org/to-regex-range/download/to-regex-range-2.1.1.tgz",
+ "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
+ "optional": true,
+ "requires": {
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1"
+ }
+ }
+ }
+ },
+ "webpack": {
+ "version": "3.12.0",
+ "resolved": "https://registry.nlark.com/webpack/download/webpack-3.12.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fwebpack%2Fdownload%2Fwebpack-3.12.0.tgz",
+ "integrity": "sha1-P540NgNwYC/PY56Xk520hvTsDXQ=",
+ "requires": {
+ "acorn": "^5.0.0",
+ "acorn-dynamic-import": "^2.0.0",
+ "ajv": "^6.1.0",
+ "ajv-keywords": "^3.1.0",
+ "async": "^2.1.2",
+ "enhanced-resolve": "^3.4.0",
+ "escope": "^3.6.0",
+ "interpret": "^1.0.0",
+ "json-loader": "^0.5.4",
+ "json5": "^0.5.1",
+ "loader-runner": "^2.3.0",
+ "loader-utils": "^1.1.0",
+ "memory-fs": "~0.4.1",
+ "mkdirp": "~0.5.0",
+ "node-libs-browser": "^2.0.0",
+ "source-map": "^0.5.3",
+ "supports-color": "^4.2.1",
+ "tapable": "^0.2.7",
+ "uglifyjs-webpack-plugin": "^0.4.6",
+ "watchpack": "^1.4.0",
+ "webpack-sources": "^1.0.1",
+ "yargs": "^8.0.2"
+ }
+ },
+ "webpack-sources": {
+ "version": "1.4.3",
+ "resolved": "https://registry.nlark.com/webpack-sources/download/webpack-sources-1.4.3.tgz",
+ "integrity": "sha1-7t2OwLko+/HL/plOItLYkPMwqTM=",
+ "requires": {
+ "source-list-map": "^2.0.0",
+ "source-map": "~0.6.1"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz",
+ "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM="
+ }
+ }
+ },
+ "which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npm.taobao.org/which/download/which-1.3.1.tgz",
+ "integrity": "sha1-pFBD1U9YBTFtqNYvn1CRjT2nCwo=",
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ },
+ "which-module": {
+ "version": "2.0.0",
+ "resolved": "https://registry.nlark.com/which-module/download/which-module-2.0.0.tgz",
+ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho="
+ },
+ "window-size": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npm.taobao.org/window-size/download/window-size-0.1.0.tgz",
+ "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0="
+ },
+ "wordwrap": {
+ "version": "0.0.2",
+ "resolved": "https://registry.nlark.com/wordwrap/download/wordwrap-0.0.2.tgz",
+ "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8="
+ },
+ "wrap-ansi": {
+ "version": "2.1.0",
+ "resolved": "https://registry.nlark.com/wrap-ansi/download/wrap-ansi-2.1.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fwrap-ansi%2Fdownload%2Fwrap-ansi-2.1.0.tgz",
+ "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
+ "requires": {
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1"
+ },
+ "dependencies": {
+ "string-width": {
+ "version": "1.0.2",
+ "resolved": "https://registry.nlark.com/string-width/download/string-width-1.0.2.tgz",
+ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+ "requires": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ }
+ }
+ }
+ },
+ "xtend": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npm.taobao.org/xtend/download/xtend-4.0.2.tgz",
+ "integrity": "sha1-u3J3n1+kZRhrH0OPZ0+jR/2121Q="
+ },
+ "y18n": {
+ "version": "3.2.2",
+ "resolved": "https://registry.nlark.com/y18n/download/y18n-3.2.2.tgz",
+ "integrity": "sha1-hckBvWRwznH8S7cjrSCbcPfyhpY="
+ },
+ "yallist": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npm.taobao.org/yallist/download/yallist-2.1.2.tgz",
+ "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
+ },
+ "yargs": {
+ "version": "8.0.2",
+ "resolved": "https://registry.nlark.com/yargs/download/yargs-8.0.2.tgz",
+ "integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=",
+ "requires": {
+ "camelcase": "^4.1.0",
+ "cliui": "^3.2.0",
+ "decamelize": "^1.1.1",
+ "get-caller-file": "^1.0.1",
+ "os-locale": "^2.0.0",
+ "read-pkg-up": "^2.0.0",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^1.0.1",
+ "set-blocking": "^2.0.0",
+ "string-width": "^2.0.0",
+ "which-module": "^2.0.0",
+ "y18n": "^3.2.1",
+ "yargs-parser": "^7.0.0"
+ },
+ "dependencies": {
+ "camelcase": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npm.taobao.org/camelcase/download/camelcase-4.1.0.tgz?cache=0&sync_timestamp=1603923709404&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcamelcase%2Fdownload%2Fcamelcase-4.1.0.tgz",
+ "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0="
+ },
+ "cliui": {
+ "version": "3.2.0",
+ "resolved": "https://registry.nlark.com/cliui/download/cliui-3.2.0.tgz",
+ "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=",
+ "requires": {
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1",
+ "wrap-ansi": "^2.0.0"
+ },
+ "dependencies": {
+ "string-width": {
+ "version": "1.0.2",
+ "resolved": "https://registry.nlark.com/string-width/download/string-width-1.0.2.tgz",
+ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+ "requires": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ }
+ }
+ }
+ }
+ }
+ },
+ "yargs-parser": {
+ "version": "7.0.0",
+ "resolved": "https://registry.nlark.com/yargs-parser/download/yargs-parser-7.0.0.tgz",
+ "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=",
+ "requires": {
+ "camelcase": "^4.1.0"
+ },
+ "dependencies": {
+ "camelcase": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npm.taobao.org/camelcase/download/camelcase-4.1.0.tgz?cache=0&sync_timestamp=1603923709404&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcamelcase%2Fdownload%2Fcamelcase-4.1.0.tgz",
+ "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0="
+ }
+ }
+ },
+ "zrender": {
+ "version": "4.3.2",
+ "resolved": "https://registry.nlark.com/zrender/download/zrender-4.3.2.tgz?cache=0&sync_timestamp=1630140908990&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fzrender%2Fdownload%2Fzrender-4.3.2.tgz",
+ "integrity": "sha1-7HQy+UFcgsc1hLa3uMR+GwFiCcY="
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..9ec433f
--- /dev/null
+++ b/package.json
@@ -0,0 +1,16 @@
+{
+ "name": "k_graph",
+ "version": "1.0.0",
+ "description": "",
+ "main": "main.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "keywords": [],
+ "author": "",
+ "license": "ISC",
+ "dependencies": {
+ "hqchart": "^1.1.10351",
+ "jquery": "^3.6.0"
+ }
+}
diff --git a/pages.json b/pages.json
new file mode 100644
index 0000000..1aea851
--- /dev/null
+++ b/pages.json
@@ -0,0 +1,16 @@
+{
+ "pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
+ {
+ "path": "pages/index/index",
+ "style": {
+ "navigationBarTitleText": "uni-app"
+ }
+ }
+ ],
+ "globalStyle": {
+ "navigationBarTextStyle": "black",
+ "navigationBarTitleText": "uni-app",
+ "navigationBarBackgroundColor": "#F8F8F8",
+ "backgroundColor": "#F8F8F8"
+ }
+}
diff --git a/pages/index/index.vue b/pages/index/index.vue
new file mode 100644
index 0000000..20d308d
--- /dev/null
+++ b/pages/index/index.vue
@@ -0,0 +1,127 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/plugins/graph.js b/plugins/graph.js
new file mode 100644
index 0000000..fbf1c8b
--- /dev/null
+++ b/plugins/graph.js
@@ -0,0 +1,15 @@
+// #ifdef H5
+import HQChart from '@/uni_modules/jones-hqchart2/js_sdk/umychart.uniapp.h5.js'
+//HQChart.JSChart.SetDomain("xxxxx.com");
+//HQChart.JSComplier.SetDomain("xxxx.com");
+// #endif
+
+// #ifndef H5
+import {JSCommon} from '@/uni_modules/jones-hqchart2/js_sdk/umychart.wechat.3.0.js'
+import {JSCommonHQStyle} from '@/uni_modules/jones-hqchart2/js_sdk/umychart.style.wechat.js'
+import {JSCommonComplier} from "@/uni_modules/jones-hqchart2/js_sdk/umychart.complier.wechat.js"
+
+//禁用日志
+JSConsole.Complier.Log=()=>{ };
+JSConsole.Chart.Log=()=>{ };
+// #endif
\ No newline at end of file
diff --git a/static/logo.png b/static/logo.png
new file mode 100644
index 0000000..b5771e2
Binary files /dev/null and b/static/logo.png differ
diff --git a/uni.scss b/uni.scss
new file mode 100644
index 0000000..a05adb4
--- /dev/null
+++ b/uni.scss
@@ -0,0 +1,76 @@
+/**
+ * 这里是uni-app内置的常用样式变量
+ *
+ * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
+ * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
+ *
+ */
+
+/**
+ * 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
+ *
+ * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
+ */
+
+/* 颜色变量 */
+
+/* 行为相关颜色 */
+$uni-color-primary: #007aff;
+$uni-color-success: #4cd964;
+$uni-color-warning: #f0ad4e;
+$uni-color-error: #dd524d;
+
+/* 文字基本颜色 */
+$uni-text-color:#333;//基本色
+$uni-text-color-inverse:#fff;//反色
+$uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息
+$uni-text-color-placeholder: #808080;
+$uni-text-color-disable:#c0c0c0;
+
+/* 背景颜色 */
+$uni-bg-color:#ffffff;
+$uni-bg-color-grey:#f8f8f8;
+$uni-bg-color-hover:#f1f1f1;//点击状态颜色
+$uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色
+
+/* 边框颜色 */
+$uni-border-color:#c8c7cc;
+
+/* 尺寸变量 */
+
+/* 文字尺寸 */
+$uni-font-size-sm:12px;
+$uni-font-size-base:14px;
+$uni-font-size-lg:16;
+
+/* 图片尺寸 */
+$uni-img-size-sm:20px;
+$uni-img-size-base:26px;
+$uni-img-size-lg:40px;
+
+/* Border Radius */
+$uni-border-radius-sm: 2px;
+$uni-border-radius-base: 3px;
+$uni-border-radius-lg: 6px;
+$uni-border-radius-circle: 50%;
+
+/* 水平间距 */
+$uni-spacing-row-sm: 5px;
+$uni-spacing-row-base: 10px;
+$uni-spacing-row-lg: 15px;
+
+/* 垂直间距 */
+$uni-spacing-col-sm: 4px;
+$uni-spacing-col-base: 8px;
+$uni-spacing-col-lg: 12px;
+
+/* 透明度 */
+$uni-opacity-disabled: 0.3; // 组件禁用态的透明度
+
+/* 文章场景相关 */
+$uni-color-title: #2C405A; // 文章标题颜色
+$uni-font-size-title:20px;
+$uni-color-subtitle: #555555; // 二级标题颜色
+$uni-font-size-subtitle:26px;
+$uni-color-paragraph: #3F536E; // 文章段落颜色
+$uni-font-size-paragraph:15px;
diff --git a/uni_modules/jones-hqchart2/changelog.md b/uni_modules/jones-hqchart2/changelog.md
new file mode 100644
index 0000000..1cae04d
--- /dev/null
+++ b/uni_modules/jones-hqchart2/changelog.md
@@ -0,0 +1,274 @@
+## 1.1.10333(2021-09-13)
+10332 叠加指标支持VERTLINE,HORLINE
+10330 增加叠加指标移动到新窗口,MoveOverlayIndexToNewWindow
+10328 K线图支持 IsFixXLastTime
+10326 APIScriptIndex派生CopyTo虚函数
+10325 增加叠加指标移动
+10324 小程序MULTI_LINE 支持设置线段宽度
+10322 ChartMultiLine 支持设置线段宽度
+## 1.1.10321(2021-09-09)
+10320 AddIndexWindow()修正OverlayIndexType参数位置写错了
+10318 单行显示指标标题支持横屏
+10316 1. 修正IChartFramePainting::ClearCoordinateText()没有判断Message字段是否有效
+ 2. 修正HQTradeFrame::Draw()在动画场景时不自动调整左右边框间距
+10315 叠加指标标题支持单行显示
+## 1.1.10309(2021-09-01)
+10309 小程序修正分时图ChartStickLine柱子太粗了。
+## 1.1.10306(2021-08-31)
+10305 修正uniapp分时图指标工具栏$报错
+10302 修正OnTouchDBClick()手势坐标没有转换到K线图相对坐标
+
+## 1.1.10301 (2021-08-27)
+增加用户协议
+10285 修正DrawInsideHorizontal,DrawCustomHorizontal没有处理最小化窗口指标
+10284 小程序增加双击副图缩放指标窗口
+
+## 1.1.10283(2021-08-22)
+10282 小程序JSChartContainer::FullDraw()数据加载去掉坐标文字
+10281 显示数据加载时, 不显示刻度文字
+10276 增加手势双击缩放附图指标窗口
+10274 画图工具支持附图窗口最小化
+10273 部分图形画法支持指标窗口隐藏模式
+10271 修正右边自动调整叠加指标宽度是没有动态计算叠加刻度
+10270 增加是否启动双击缩放附图窗口配置
+10269 增加子窗口双击缩放
+
+## 1.1.10265(2021-08-17)
+10264 修正KLineChartContainer::Update()没有更新Y轴坐标分割线数据
+10263 DrawCustomItem() 支持多行自定义刻度文字
+## 1.1.10251(2021-08-12)
+10250 小程序指标翻译器函数翻译代码整理
+10249 指标解释器函数解释代码整理
+10247 小程序指标翻译器增加部分字符串函数翻译
+10245 指标翻译器增加部分字符串函数翻译
+10241 ON_TITLE_DRAW事件增加叠加股票信息
+## 1.1.10238(2021-08-09)
+10237 h5修正左右边框间距自动调整没有考虑筹码图宽度
+10235 h5K线图边框间距自适应支持横屏
+10234 小程序自动调整左右边框距离支持横屏
+10233 小程序K线图支持左右边框间距根据刻度文字自动调整
+10230 修正拖拽指标边框触发区间选择
+10227 h5K线图增加左右两侧边框间距根据刻度自动调整
+## 1.1.110226(2021-08-09)
+10225 小程序修正指标翻译是LLVBARS,HHVBARS报错
+10223 K线增加复权因子读取.
+10222 指标翻译器修正HHVBARS, LLVBARS报错
+10221 增加复权使用复权因子算法
+## 1.1.110220(2021-08-05)
+10219 修正 ChartMinutePriceLine::GetTooltipData()报错
+10217 h5信息地雷数据支持修改域名
+## 1.1.110216(2021-08-04)
+10216 小程序修正百分比坐标Y轴超出刻度范围
+10214 修正K线百分比坐标超出当前Y轴范围
+10212 修正分笔图十字光标区域背景最右边溢出
+10210 分笔图增加区间背景
+10209 JsonDataToTickData() 每个分笔数据的前收盘使用当日的前收盘
+10208 分笔图支持tooltip提示信息
+## 1.1.110189(2021-07-27)
+10189 修正小程序MinuteFrame里的成员变量DataWidth, DistanceWidth 没有设置为1
+10188 OnDoubleClick() 代码整理
+10187 小程序CallFunctionExplain() 增加函数不存在报错
+10185 CallFunctionExplain()增加函数不存在报错
+10183 十字光标竖线支持连续
+10182 K线tooltip和K线信息地雷禁止选中
+10181 判断tooltip代码整理, 独立成2个函数 PtInChartPaintTooltip,PtInOverlayChartPaintTooltip
+10179 ChartOverlayMinutePriceLine, ChartMinutePriceLine 增加函数GetTooltipData()
+10178 OnMinuteSelectRectMouseUp()增加CLICK事件通知
+## 1.1.110177(2021-07-23)
+10174 K线左右拖拽数据增加自动模式 (StepPixel=0)
+## 1.1.110173(2021-07-22)
+10172 自定义K线支持横屏
+10171 小程序K线图最大最小显示配置支持横屏
+10170 K线最大最小值显示设置支持横屏
+10169 K线图支持自定义K线颜色
+10167 ChartKLine::DrawKBar()代码整理
+## 1.1.110166(2021-07-19)
+10165 GetVariantData()增加错误提示
+10161 修正GetVariantData()外部数据对接格式错误
+10159 小程序增加INBLOCK
+10157 增加INBLOCK
+10156 小程序支持板块函数
+10154 增加板块函数
+
+## 1.1.110127(2021-07-14)
+10125 K线图增加叠加指标参数修改更新接口
+10124 去掉scss相关内容和webpack配置
+10122 修正分时图区间选择最后的结束时间点超出当前交易时间报错
+
+
+## 1.1.110119 (2021-07-12)
+10117 JSExplainer语法检测器迁移到小程序
+10115 小程序AddIndexWindow()增加SplitCount,IsShowLeftText,IsShowRightText属性设置
+10114 AddIndexWindow() 增加SplitCount属性
+10110 增加区间统计框关闭以后, 操作选中区域完毕以后,弹出对应的菜单或框
+## 1.1.10095(2021-07-07)
+10094 ChangeIndexWindowCount() 增加IsShowLeftText, IsShowRightText设置
+10092 AddIndexWindow() 增加IsShowLeftText,IsShowRightText设置
+10090 修正多日分时图切换最大最小值没有清空
+
+## 1.1.10087(2021-07-01)
+10087 小程序修正分时图RecvMinuteData()报错
+## 1.1.10086(2021-07-01)
+10086 小程序国内期货增加新品种
+10085 小程序DynamicTitleData增加是否显示标识
+10084 小程序修正IFrameSplitOperator.IsString()空字符串判断错误
+10083 IFrameSplitOperator.IsString()修正""空字符串判断错误
+10081 MULTI_BAR叠加指标增加往标题实例中设置数据
+10080 自定义多柱子增加数据设置到标题
+## 1.1.10076(2021-06-29)
+10074 小程序分时图Y轴增加涨跌停坐标轴
+10073 小程序 分时图Y周支持根据最高最低加分割
+10072 1. 小程序 IChangeStringFormat 迁移到umychart.framesplit.wechart.js中
+ 2. 小程序 增加IChangeStringFormat工厂类
+10068 K线tooltip和标题信息成交量A股统一改成手单位
+## 1.1.10065(2021-06-28)
+10064 修正分时图没有判断是否支持区间选择导致报错
+## 1.1.10063(2021-06-28)
+10061 小程序十字光标X轴日期文字支持3种格式 0=YYYY-MM-DD 1=YYYY/MM/DD 2=YYYY/MM/DD/W 3=DD/MM/YYYY
+10060 十字光标X轴日期显示 支持YY/MM/YYYY
+10057 修正百分比坐标价格和百分比两个颜色配置颠倒了.
+10055 修正分笔K线区间统计框起始时间格式显示不对.
+## 1.1.10040(2021-06-25)
+10039 K线图支持上下拖拽
+10037 分笔K线增加支持叠加指标
+10035 分笔K线数据更新增加2.0格式
+10034 1. 分笔K线全量数据增加新的数据格式
+ 2. 分笔标题信息和tooltip显示样式修改
+ 3. 分笔增加百分比坐标
+
+## 1.1.9984(2021-06-17)
+9983 修正SplitLogarithmicXYCoordinate()预留高度为负数是,显示错误
+9978 修正KLineChartContainer::ChangeIndexWindowCount() 显示错位
+ 增加AddIndexWindow() 添加指标窗口
+9977 K线图增加事件ON_SPLIT_XCOORDINATE
+9958 KLineChartContainer.JsonDataToHistoryData(), KLineChartContainer.JsonDataToMinuteRealtimeData(), KLineChartContainer.JsonDataToMinuteHistoryData() 去掉价格<0的无效价格判断.
+9954 ChartVericaltLine, ChartHorizontalLine 支持横屏
+9953 绘图函数HORLINE()支持单数值条件
+9951 增加绘图函数HORLINE
+9950 增加绘图函数VERTLINE
+9949 部分替换 for(var i in array ) 改成 for(var i=0;i
+## 1.1.9948(2021-06-12)
+9948 小程序分时图和K线图十字光标移动优化
+9947 小程序增加分时图十字光标移动延迟绘图间隔设置
+## 1.1.9946(2021-06-12)
+9946 小程序优化分时图十字光标移动效率
+9945 小程序修正ChangePeriod()未完成数据下载切换周期报错
+9942 小程序ChartMinutePriceLine迁移到umychart.chartpaint.wechart.js中
+## 1.1.9938(2021-06-10)
+9937 小程序K线训练增加是否显示最高最低价格显示控制
+9936, 9935 把部分数组循环遍历 (var i in array) 改成=> (var i=0;i
+## 1.1.9933(2021-06-09)
+9931 小程序更新定时器增加判断是否图形已销毁
+9925 期货增加 郑州商品交易所-红枣(CJ)
+9921 JsonDataToMinuteDataArray 修正跨天数据 日期时间显示错误
+9919 修正分时图标题高度没有设置为0
+9917 大盘指数(INDEXA, INDEXC....)支持对3放数据对接
+## 1.1.9907(2021-06-06)
+9907 修正IFrameSplitOperator::IntegerCoordinateSplit() 负数最小值计算错误
+9902 增加指标标题绘制回调函数 ON_INDEXTITLE_DRAW
+## 1.1.9901(2021-06-06)
+9900 小程序修正IFrameSplitOperator::IntegerCoordinateSplit()最低价计算错误
+9899 IFrameSplitOperator::IntegerCoordinateSplit() 修正最低价计算错误
+## 1.1.9893(2021-06-04)
+9892 小程序IFrameSplitOperator::IntegerCoordinateSplit()算法优化
+9890 IFrameSplitOperator::IntegerCoordinateSplit() 修正计算错误
+9886 增加多日集合竞价最新数据更新
+9885 修正FrameSplitY::GetCallAcutionSplitY() 多日分时Y轴多算了一个刻度
+ 多日分时图集合竞价Y轴统一最大,最小值
+## 1.1.9864(2021-05-30)
+9863 分时图集合竞价十字光标显示最近的有效数据
+9862 多日集合竞价十字光标支持Y轴数据显示
+9861 多日分时图Y轴显示集合竞价刻度
+## 1.1.9792(2021-05-21)
+9792 小程序
+1. 修正DRAWRECTREL()位置正确性没有判断
+2. Y轴内部刻度增加属性YTextBaseline,支持上下位置可以配置
+9790 FrameSplitMinutePriceY::GetMaxMin() 修正计算错误. Y轴内部刻度文字支持上下位子配置
+9788 导出 CoordinateInfo
+
+## 1.1.9759(2021-05-19)
+9758 DynamicMinuteTitlePainting调整集合竞价1.0数据格式显示样式
+9756 小程序 ChartVolStick柱子高度<1,统一显示为1
+9754 ChartVolStick() 高度小于1, 统一调整为1
+9748 ShowSelectRect() 分时图显示位置调整
+9747 分时图增加区间选择接口
+9746 RequestDragMinuteData, RequestDragDayData 数据回调增加周期和复权参数
+9743 集合竞价支持绘制点
+
+
+## 1.1.9725(2021-05-15)
+9724 修正ChartMultiHtmlDom() 在页面放大倍数以后, DOM坐标计算错误
+9719 小程序 JSComplier.Execute() 去掉ios回报错的日志
+## 1.1.9694(2021-05-10)
+9694 小程序 1. JSCHART_EVENT_ID定义迁移到umychart.data.wechart.js里面
+ 2. 支持 JSCHART_EVENT_ID.ON_SPLIT_YCOORDINATE 事件
+9687 小程序ChartBorder增加 GetBorder(),GetHScreenBorder()
+## 1.1.9683(2021-05-09)
+修改readme
+## 1.1.9682(2021-05-09)
+修改readme
+## 1.1.9681(2021-05-09)
+9671 增加分时图集合竞价关闭按钮
+9670 分时图集合竞价支持横屏
+9668 增加收盘集合竞价
+## 1.1.9654(2021-05-04)
+9653 1.分时图双击事件
+ 2.集合竞价宽度设置
+9651 修正ChartMinutePriceLine::DrawBeforeOpen()报错
+9649 MULTI_LINE多线段支持"C","H"等特殊标识价格
+9648 1.修正分时图叠加指标共享Y轴横屏没有读取主图Y轴信息
+ 2.ChartMultiSVGIcon 使用GetBorder获取坐标信息
+9647 分时图集合竞价框架重新调整
+## 1.1.9617(2021-04-28)
+9616 修正IsSHSZStockA() 没有包含300创业板
+9610 UpdateFrameMaxMin() 主图计算Y轴最大最小值增加叠加指标数据
+9604 分时图和K线主图支持ON_SPLIT_YCOORDINATE事件
+9599 Y轴分割函数,增加是否支持Y轴缩放查询接口
+9597 增加 Y轴分割刻度回调事件
+
+
+## 1.1.9536(2021-04-23)
+增加插件教程说明
+## 1.1.9535(2021-04-22)
+增加HQChart模板样例
+## 1.1.9534(2021-04-22)
+9532 公告信息地雷支持去重更新
+9529 信息地理拖拽下载数据以后,支持更新调用
+9520 增加AB波浪尺
+## 1.1.9518(2021-04-21)
+9517 修正多日分时图更新当天数据时,叠加指标没有重新计算
+9516 小程序增加ON_PHONE_TOUCH事件回调
+9509 修正OverlayScriptIndex::CreateTextLine()画法保存错误
+9501 1. 信息地雷顶部画不下了, 移动下面画
+ 2. 修正单击K线和双击K线同时触发回调的问题
+
+## 1.1.9500(2021-04-19)
+9481 增加画图工具图标
+9479 小程序修正BARSSINCEN算法错误
+9478 修正BARSSINCEN算法
+9477 修正 JSCHART_OPERATOR_ID.OP_LEFT_ZOOM_OUT 数据索引计算错误
+9497 走势图支持后台指标API数据
+9496 修正"BindOverlayPositionData", "ClearBindOverlayPositionData" 指标变量写错了.
+9495 分时图支持叠加指标
+9499 h5增加手势事件回调ON_PHONE_TOUCH.
+
+## 1.1.9473(2021-04-12)
+9472 修正K线数据更新以后叠加指标没有执行更新
+9471 小程序"CIRCLEDOT","POINTDOT"点半径支持设置
+9469 CIRCLEDOT, POINTDOT支持半径大小设置
+9466 小程序ChartOperator右移K线支持下载功能
+9465 小程序COLORSTICK支持标题字体颜色设置
+9469 COLORSTICK 支持后面增加颜色控制标题的字体颜色
+9462 增加点击回调事件
+9458 ChartOperator() 数据右移增加,历史数据下载功能
+## 1.1.9444(2021-04-08)
+9443 增加K线叠加指标是否显示指标名字配置
+9441 ChangeIndexTemplate() 支持指标标题字体设置
+9338 ChartSingleText 获取X轴坐标分时图和K线图分开
+
+## 1.1.9417(2021-04-01)
+9416 增加水平线段
+## 1.1.9416(2021-03-31)
+增加测试用例项目
+## 1.1.9415(2021-03-31)
+把原来hqchart改成uniapp插件模式. 版本号 1.9415
diff --git a/uni_modules/jones-hqchart2/js_sdk/HQChartControl.vue b/uni_modules/jones-hqchart2/js_sdk/HQChartControl.vue
new file mode 100644
index 0000000..df0b016
--- /dev/null
+++ b/uni_modules/jones-hqchart2/js_sdk/HQChartControl.vue
@@ -0,0 +1,511 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/jones-hqchart2/js_sdk/umychart.chartpaint.wechat.js b/uni_modules/jones-hqchart2/js_sdk/umychart.chartpaint.wechat.js
new file mode 100644
index 0000000..08d3733
--- /dev/null
+++ b/uni_modules/jones-hqchart2/js_sdk/umychart.chartpaint.wechat.js
@@ -0,0 +1,6134 @@
+/*
+ copyright (c) 2018 jones
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ 开源项目 https://github.com/jones2000/HQChart
+
+ jones_2000@163.com
+
+ 小程序图形库
+*/
+
+//行情数据结构体 及涉及到的行情算法(复权,周期等)
+import
+{
+ JSCommon_ChartData as ChartData, JSCommon_HistoryData as HistoryData,
+ JSCommon_SingleData as SingleData, JSCommon_MinuteData as MinuteData,
+ JSCommon_Rect as Rect,
+} from "./umychart.data.wechat.js";
+
+import
+{
+ JSCommonResource_Global_JSChartResource as g_JSChartResource,
+} from './umychart.resource.wechat.js'
+
+import
+{
+ JSCommonSplit_IFrameSplitOperator as IFrameSplitOperator,
+} from './umychart.framesplit.wechat.js'
+
+import
+{
+ JSCommonCoordinateData as JSCommonCoordinateData,
+ JSCommonCoordinateData_MARKET_SUFFIX_NAME as MARKET_SUFFIX_NAME
+} from "./umychart.coordinatedata.wechat.js";
+
+//配色
+function JSChartPaintResource()
+{
+ //指标不支持信息
+ this.Index=
+ {
+ NotSupport : { Font: "14px 微软雅黑", TextColor: "rgb(52,52,52)" }
+ }
+}
+var g_JSChartPaintResource = new JSChartPaintResource();
+
+
+//图新画法接口类
+function IChartPainting()
+{
+ this.Canvas; //画布
+ this.ChartBorder; //边框信息
+ this.ChartFrame; //框架画法
+ this.Name; //名称
+ this.ClassName = 'IChartPainting'; //类名
+ this.Data = new ChartData(); //数据区
+
+ this.NotSupportMessage = null;
+ this.MessageFont = g_JSChartPaintResource.Index.NotSupport.Font;
+ this.MessageColor = g_JSChartPaintResource.Index.NotSupport.TextColor;
+
+ this.IsDrawFirst = false; //是否比K线先画
+ this.IsShow = true; //是否显示
+
+ this.Draw = function () { }
+
+ this.IsMinuteFrame=function()
+ {
+ var isMinute=(this.ChartFrame.ClassName=="MinuteFrame" || this.ChartFrame.ClassName=="MinuteHScreenFrame");
+ return isMinute
+ }
+
+ this.DrawNotSupportmessage = function ()
+ {
+ this.Canvas.font = this.MessageFont;
+ this.Canvas.fillStyle = this.MessageColor;
+
+ var left = this.ChartBorder.GetLeft();
+ var width = this.ChartBorder.GetWidth();
+ var top = this.ChartBorder.GetTopEx();
+ var height = this.ChartBorder.GetHeightEx();
+
+ var x = left + width / 2;
+ var y = top + height / 2;
+
+ this.Canvas.textAlign = "center";
+ this.Canvas.textBaseline = "middle";
+ this.Canvas.fillText(this.NotSupportMessage, x, y);
+ }
+
+ this.GetTooltipData = function (x, y, tooltip)
+ {
+ return false;
+ }
+
+ this.GetMaxMin = function ()
+ {
+ var xPointCount = this.ChartFrame.XPointCount;
+ var range = {};
+ range.Min = null;
+ range.Max = null;
+
+ if (!this.Data || !this.Data.Data) return range;
+
+ for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j)
+ {
+ var value = this.Data.Data[i];
+ if (value == null || isNaN(value)) continue;
+
+ if (range.Max == null) range.Max = value;
+ if (range.Min == null) range.Min = value;
+
+ if (range.Max < value) range.Max = value;
+ if (range.Min > value) range.Min = value;
+ }
+
+ return range;
+ }
+
+ this.GetDynamicFont = function (dataWidth) //根据宽度自动获取对应字体
+ {
+ var font;
+ if (dataWidth < 5) font = '4px Arial'; //字体根据数据宽度动态调整
+ else if (dataWidth < 7) font = '6px Arial';
+ else if (dataWidth < 9) font = '8px Arial';
+ else if (dataWidth < 11) font = '10px Arial';
+ else if (dataWidth < 13) font = '12px Arial';
+ else if (dataWidth < 15) font = '14px Arial';
+ else font = '16px Arial';
+
+ return font;
+ }
+
+ this.GetDynamicFontEx=function(dataWidth, distanceWidth, maxSize, minSize, zoom, fontname) //根据宽度自动获取对应字体
+ {
+ if (maxSize==minSize)
+ {
+ var font=`${maxSize.toFixed(0)}px ${fontname}` ;
+ return font;
+ }
+
+ var fontSize=(dataWidth+distanceWidth);
+ if (zoom)
+ {
+ if (zoom.Type==0)
+ {
+ if (zoom.Value>0) fontSize=(dataWidth*zoom.Value);
+ }
+ else if (zoom.Type==1)
+ {
+ if (zoom.Value>0) fontSize=(dataWidth+distanceWidth)*zoom.Value;
+ }
+ else if (zoom.Type==2)
+ {
+ if (IFrameSplitOperator.IsNumber(zoom.Value))
+ fontSize=(dataWidth+distanceWidth) + (2*zoom.Value);
+ }
+ }
+
+ if (fontSizemaxSize) fontSize=maxSize;
+
+ var font=`${fontSize.toFixed(0)}px ${fontname}` ;
+ return font;
+ }
+
+ this.SetFillStyle = function (color, x0, y0, x1, y1)
+ {
+ if (Array.isArray(color))
+ {
+ let gradient = this.Canvas.createLinearGradient(x0, y0, x1, y1);
+ var offset = 1 / (color.length);
+ for (var i in color)
+ {
+ gradient.addColorStop(i * offset, color[i]);
+ }
+ this.Canvas.fillStyle = gradient;
+ }
+ else
+ {
+ this.Canvas.fillStyle = color;
+ }
+ }
+}
+
+//K线画法
+function ChartKLine()
+{
+ this.newMethod = IChartPainting; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.ClassName = 'ChartKLine';
+ this.Symbol; //股票代码
+ this.DrawType = 0; // 0=K线 1=收盘价线 2=美国线 3=空心K线柱子 4=收盘价面积
+ this.CloseLineColor = g_JSChartResource.CloseLineColor;
+ this.CloseLineAreaColor = g_JSChartResource.CloseLineAreaColor;
+ this.UpColor = g_JSChartResource.UpBarColor;
+ this.DownColor = g_JSChartResource.DownBarColor;
+ this.UnchagneColor = g_JSChartResource.UnchagneBarColor; //平盘
+ this.ColorData; //五彩K线颜色 >0 UpColor 其他 DownColor
+ this.TradeData; //交易系统 包含买卖数据{Buy:, Sell:}
+
+ this.IsShowMaxMinPrice = true; //是否显示最大最小值
+ this.TextFont = g_JSChartResource.KLine.MaxMin.Font;
+ this.TextColor = g_JSChartResource.KLine.MaxMin.Color;
+ this.InfoPointColor = g_JSChartResource.KLine.Info.Color;
+ this.InfoPointColor2 = g_JSChartResource.KLine.Info.Color2;
+ this.InfoDrawType = 0; //0=在底部画远点 1=在最低价画三角
+
+ this.PtMax; //最大值的位置
+ this.PtMin; //最小值的位置
+
+ this.MinBarWidth=g_JSChartResource.MinKLineBarWidth; //最小的柱子宽度
+
+ this.DrawAKLine = function () //美国线
+ {
+ var isHScreen = (this.ChartFrame.IsHScreen === true);
+ var dataWidth = this.ChartFrame.DataWidth;
+ var distanceWidth = this.ChartFrame.DistanceWidth;
+ var xOffset = this.ChartBorder.GetLeft() + distanceWidth / 2.0 + g_JSChartResource.FrameLeftMargin;
+ if (isHScreen) xOffset = this.ChartBorder.GetTop() + distanceWidth / 2.0 + g_JSChartResource.FrameLeftMargin;
+ var chartright = this.ChartBorder.GetRight();
+ if (isHScreen) chartright = this.ChartBorder.GetBottom();
+ var xPointCount = this.ChartFrame.XPointCount;
+
+ var ptMax = { X: null, Y: null, Value: null, Align: 'left' };
+ var ptMin = { X: null, Y: null, Value: null, Align: 'left' };
+ for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth))
+ {
+ var data = this.Data.Data[i];
+ if (data.Open == null || data.High == null || data.Low == null || data.Close == null) continue;
+
+ var left = xOffset;
+ var right = xOffset + dataWidth;
+ if (right > chartright) break;
+ var x = left + (right - left) / 2;
+ var yLow = this.ChartFrame.GetYFromData(data.Low);
+ var yHigh = this.ChartFrame.GetYFromData(data.High);
+ var yOpen = this.ChartFrame.GetYFromData(data.Open);
+ var yClose = this.ChartFrame.GetYFromData(data.Close);
+
+ if (ptMax.Value == null || ptMax.Value < data.High) //求最大值
+ {
+ ptMax.X = x;
+ ptMax.Y = yHigh;
+ ptMax.Value = data.High;
+ ptMax.Align = j < xPointCount / 2 ? 'left' : 'right';
+ }
+
+ if (ptMin.Value == null || ptMin.Value > data.Low) //求最小值
+ {
+ ptMin.X = x;
+ ptMin.Y = yLow;
+ ptMin.Value = data.Low;
+ ptMin.Align = j < xPointCount / 2 ? 'left' : 'right';
+ }
+
+ if (data.Open < data.Close) this.Canvas.strokeStyle = this.UpColor; //阳线
+ else if (data.Open > data.Close) this.Canvas.strokeStyle = this.DownColor; //阳线
+ else this.Canvas.strokeStyle = this.UnchagneColor; //平线
+
+ this.Canvas.beginPath(); //最高-最低
+ if (isHScreen) {
+ this.Canvas.moveTo(yHigh, ToFixedPoint(x));
+ this.Canvas.lineTo(yLow, ToFixedPoint(x));
+ }
+ else {
+ this.Canvas.moveTo(ToFixedPoint(x), yHigh);
+ this.Canvas.lineTo(ToFixedPoint(x), yLow);
+ }
+
+ this.Canvas.stroke();
+
+ if (dataWidth >= this.MinBarWidth) {
+ this.Canvas.beginPath(); //开盘
+ if (isHScreen) {
+ this.Canvas.moveTo(ToFixedPoint(yOpen), left);
+ this.Canvas.lineTo(ToFixedPoint(yOpen), x);
+ }
+ else {
+ this.Canvas.moveTo(left, ToFixedPoint(yOpen));
+ this.Canvas.lineTo(x, ToFixedPoint(yOpen));
+ }
+ this.Canvas.stroke();
+
+ this.Canvas.beginPath(); //收盘
+ if (isHScreen) {
+ this.Canvas.moveTo(ToFixedPoint(yClose), right);
+ this.Canvas.lineTo(ToFixedPoint(yClose), x);
+ }
+ else {
+ this.Canvas.moveTo(right, ToFixedPoint(yClose));
+ this.Canvas.lineTo(x, ToFixedPoint(yClose));
+ }
+ this.Canvas.stroke();
+ }
+
+ if (this.Data.DataType == 0 && ChartData.IsDayPeriod(this.Data.Period,true)) //信息地雷
+ {
+ var infoItem = { X: x, Xleft: left, XRight: right, YMax: yHigh, YMin: yLow, DayData: data, Index: j };
+ this.DrawInfoDiv(infoItem);
+ }
+ }
+
+ this.PtMax = ptMax;
+ this.PtMin = ptMin;
+ }
+
+ this.DrawCloseLine = function () //收盘价线
+ {
+ var isHScreen = (this.ChartFrame.IsHScreen === true);
+ var dataWidth = this.ChartFrame.DataWidth;
+ var distanceWidth = this.ChartFrame.DistanceWidth;
+ var xOffset = this.ChartBorder.GetLeft() + distanceWidth / 2.0 + 2.0;
+ if (isHScreen) xOffset = this.ChartBorder.GetTop() + distanceWidth / 2.0 + 2.0;
+ var chartright = this.ChartBorder.GetRight();
+ if (isHScreen) chartright = this.ChartBorder.GetBottom();
+ var xPointCount = this.ChartFrame.XPointCount;
+
+ var bFirstPoint = true;
+ this.Canvas.beginPath();
+ this.Canvas.strokeStyle = this.CloseLineColor;
+ for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth)) {
+ var data = this.Data.Data[i];
+ if (data.Open == null || data.High == null || data.Low == null || data.Close == null) continue;
+
+ var left = xOffset;
+ var right = xOffset + dataWidth;
+ if (right > chartright) break;
+ var x = left + (right - left) / 2;
+ var yClose = this.ChartFrame.GetYFromData(data.Close);
+
+ if (bFirstPoint) {
+ if (isHScreen) this.Canvas.moveTo(yClose, x);
+ else this.Canvas.moveTo(x, yClose);
+ bFirstPoint = false;
+ }
+ else {
+ if (isHScreen) this.Canvas.lineTo(yClose, x);
+ else this.Canvas.lineTo(x, yClose);
+ }
+ }
+
+ if (bFirstPoint == false) this.Canvas.stroke();
+ }
+
+ this.DrawCloseArea = function () //收盘价面积
+ {
+ var isHScreen = (this.ChartFrame.IsHScreen === true);
+ var dataWidth = this.ChartFrame.DataWidth;
+ var distanceWidth = this.ChartFrame.DistanceWidth;
+ var xOffset = this.ChartBorder.GetLeft() + distanceWidth / 2.0 + 2.0;
+ if (isHScreen) xOffset = this.ChartBorder.GetTop() + distanceWidth / 2.0 + 2.0;
+ var chartright = this.ChartBorder.GetRight();
+ if (isHScreen) chartright = this.ChartBorder.GetBottom();
+ var xPointCount = this.ChartFrame.XPointCount;
+
+ var bFirstPoint = true;
+ var firstPoint = null;
+ this.Canvas.beginPath();
+ this.Canvas.strokeStyle = this.CloseLineColor;
+ for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth)) {
+ var data = this.Data.Data[i];
+ if (data.Open == null || data.High == null || data.Low == null || data.Close == null) continue;
+
+ var left = xOffset;
+ var right = xOffset + dataWidth;
+ if (right > chartright) break;
+ var x = left + (right - left) / 2;
+ var yClose = this.ChartFrame.GetYFromData(data.Close);
+
+ if (bFirstPoint) {
+ if (isHScreen) {
+ this.Canvas.moveTo(yClose, x);
+ firstPoint = { X: yClose, Y: x };
+ }
+ else {
+ this.Canvas.moveTo(x, yClose);
+ firstPoint = { X: x, Y: yClose };
+ }
+ bFirstPoint = false;
+ }
+ else {
+ if (isHScreen) this.Canvas.lineTo(yClose, x);
+ else this.Canvas.lineTo(x, yClose);
+ }
+ }
+
+ if (bFirstPoint) return;
+
+ this.Canvas.stroke();
+ //画面积
+ if (isHScreen) {
+ this.Canvas.lineTo(this.ChartBorder.GetLeft(), x);
+ this.Canvas.lineTo(this.ChartBorder.GetLeft(), firstPoint.Y);
+ }
+ else {
+ this.Canvas.lineTo(x, this.ChartBorder.GetBottom());
+ this.Canvas.lineTo(firstPoint.X, this.ChartBorder.GetBottom());
+ }
+ this.Canvas.closePath();
+
+ if (Array.isArray(this.CloseLineAreaColor)) {
+ if (isHScreen) {
+ let gradient = this.Canvas.createLinearGradient(this.ChartBorder.GetRightEx(), this.ChartBorder.GetTop(), this.ChartBorder.GetLeft(), this.ChartBorder.GetTop());
+ gradient.addColorStop(0, this.CloseLineAreaColor[0]);
+ gradient.addColorStop(1, this.CloseLineAreaColor[1]);
+ this.Canvas.fillStyle = gradient;
+ }
+ else {
+ let gradient = this.Canvas.createLinearGradient(firstPoint.X, this.ChartBorder.GetTopEx(), firstPoint.X, this.ChartBorder.GetBottom());
+ gradient.addColorStop(0, this.CloseLineAreaColor[0]);
+ gradient.addColorStop(1, this.CloseLineAreaColor[1]);
+ this.Canvas.fillStyle = gradient;
+ }
+ }
+ else {
+ this.Canvas.fillStyle = this.CloseLineAreaColor;
+ }
+ this.Canvas.fill();
+ }
+
+ this.DrawKBar = function ()
+ {
+ var isHScreen = (this.ChartFrame.IsHScreen === true);
+ var dataWidth = this.ChartFrame.DataWidth;
+ var distanceWidth = this.ChartFrame.DistanceWidth;
+ var xOffset = this.ChartBorder.GetLeft() + distanceWidth / 2.0 + 2.0;
+ var chartright = this.ChartBorder.GetRight();
+ var xPointCount = this.ChartFrame.XPointCount;
+
+ if (isHScreen) {
+ xOffset = this.ChartBorder.GetTop() + distanceWidth / 2.0 + 2.0;
+ chartright = this.ChartBorder.GetBottom();
+ }
+
+ var ptMax = { X: null, Y: null, Value: null, Align: 'left' };
+ var ptMin = { X: null, Y: null, Value: null, Align: 'left' };
+
+ var upColor = this.UpColor;
+ var downColor = this.DownColor;
+ var unchagneColor = this.UnchagneColor;
+
+ for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth))
+ {
+ var data = this.Data.Data[i];
+ if (data.Open == null || data.High == null || data.Low == null || data.Close == null) continue;
+
+ var left = xOffset;
+ var right = xOffset + dataWidth;
+ if (right > chartright)
+ break;
+
+ var x = left + (right - left) / 2;
+ var yLow = this.ChartFrame.GetYFromData(data.Low);
+ var yHigh = this.ChartFrame.GetYFromData(data.High);
+ var yOpen = this.ChartFrame.GetYFromData(data.Open);
+ var yClose = this.ChartFrame.GetYFromData(data.Close);
+ var y = yHigh;
+
+ if (ptMax.Value == null || ptMax.Value < data.High) //求最大值
+ {
+ ptMax.X = x;
+ ptMax.Y = yHigh;
+ ptMax.Value = data.High;
+ ptMax.Align = j < xPointCount / 2 ? 'left' : 'right';
+ }
+
+ if (ptMin.Value == null || ptMin.Value > data.Low) //求最小值
+ {
+ ptMin.X = x;
+ ptMin.Y = yLow;
+ ptMin.Value = data.Low;
+ ptMin.Align = j < xPointCount / 2 ? 'left' : 'right';
+ }
+
+ if (this.ColorData) ///五彩K线颜色设置
+ {
+ if (i < this.ColorData.length)
+ upColor = downColor = unchagneColor = (this.ColorData[i] > 0 ? this.UpColor : this.DownColor);
+ else
+ upColor = downColor = unchagneColor = this.DownColor;
+ }
+
+ if (data.Open < data.Close) //阳线
+ {
+ if (dataWidth >= this.MinBarWidth)
+ {
+ this.Canvas.strokeStyle = upColor;
+ if (data.High > data.Close) //上影线
+ {
+ this.Canvas.beginPath();
+ if (isHScreen)
+ {
+ this.Canvas.moveTo(ToFixedPoint(y), ToFixedPoint(x));
+ this.Canvas.lineTo(ToFixedPoint(this.DrawType == 3 ? Math.max(yClose, yOpen) : yClose), ToFixedPoint(x));
+ }
+ else
+ {
+ this.Canvas.moveTo(ToFixedPoint(x), ToFixedPoint(y));
+ this.Canvas.lineTo(ToFixedPoint(x), ToFixedPoint(this.DrawType == 3 ? Math.min(yClose, yOpen) : yClose));
+ }
+ this.Canvas.stroke();
+ y = yClose;
+ }
+ else
+ {
+ y = yClose;
+ }
+
+ this.Canvas.fillStyle = upColor;
+ if (isHScreen)
+ {
+ if (Math.abs(yOpen - y) < 1)
+ {
+ this.Canvas.fillRect(ToFixedRect(y), ToFixedRect(left), 1, ToFixedRect(dataWidth)); //高度小于1,统一使用高度1
+ }
+ else
+ {
+ if (this.DrawType == 3) //空心柱
+ {
+ this.Canvas.beginPath();
+ this.Canvas.rect(ToFixedPoint(y), ToFixedPoint(left), ToFixedRect(yOpen - y), ToFixedRect(dataWidth));
+ this.Canvas.stroke();
+ }
+ else
+ {
+ //宽度是负数竟然不会画, h5就可以
+ //this.Canvas.fillRect(ToFixedRect(y), ToFixedRect(left), ToFixedRect(yOpen - y), ToFixedRect(dataWidth));
+ this.Canvas.fillRect(ToFixedRect(Math.min(yOpen, y)), ToFixedRect(left), ToFixedRect(Math.abs(yOpen - y)), ToFixedRect(dataWidth));
+ }
+ }
+ }
+ else
+ {
+ if (Math.abs(yOpen - y) < 1)
+ {
+ this.Canvas.fillRect(ToFixedRect(left), ToFixedRect(y), ToFixedRect(dataWidth), 1); //高度小于1,统一使用高度1
+ }
+ else
+ {
+ if (this.DrawType == 3) //空心柱
+ {
+ this.Canvas.beginPath();
+ this.Canvas.rect(ToFixedPoint(left), ToFixedPoint(y), ToFixedRect(dataWidth), ToFixedRect(yOpen - y));
+ this.Canvas.stroke();
+ }
+ else
+ {
+ this.Canvas.fillRect(ToFixedRect(left), ToFixedRect(y), ToFixedRect(dataWidth), ToFixedRect(yOpen - y));
+ }
+ }
+ }
+
+ if (data.Open > data.Low) //下影线
+ {
+ this.Canvas.beginPath();
+ if (isHScreen)
+ {
+ this.Canvas.moveTo(ToFixedPoint(this.DrawType == 3 ? Math.min(yClose, yOpen) : y), ToFixedPoint(x));
+ this.Canvas.lineTo(ToFixedPoint(yLow), ToFixedPoint(x));
+ }
+ else
+ {
+ this.Canvas.moveTo(ToFixedPoint(x), ToFixedPoint(this.DrawType == 3 ? Math.max(yClose, yOpen) : y));
+ this.Canvas.lineTo(ToFixedPoint(x), ToFixedPoint(yLow));
+ }
+ this.Canvas.stroke();
+ }
+ }
+ else
+ {
+ this.Canvas.beginPath();
+ if (isHScreen)
+ {
+ this.Canvas.moveTo(yHigh, ToFixedPoint(x));
+ this.Canvas.lineTo(yLow, ToFixedPoint(x));
+ }
+ else
+ {
+ this.Canvas.moveTo(ToFixedPoint(x), yHigh);
+ this.Canvas.lineTo(ToFixedPoint(x), yLow);
+ }
+ this.Canvas.strokeStyle = upColor;
+ this.Canvas.stroke();
+ }
+ }
+ else if (data.Open > data.Close) //阴线
+ {
+ if (dataWidth >= this.MinBarWidth)
+ {
+ this.Canvas.strokeStyle = downColor;
+ if (data.High > data.Close) //上影线
+ {
+ this.Canvas.beginPath();
+ if (isHScreen)
+ {
+ this.Canvas.moveTo(ToFixedPoint(y), ToFixedPoint(x));
+ this.Canvas.lineTo(ToFixedPoint(yOpen), ToFixedPoint(x));
+ }
+ else
+ {
+ this.Canvas.moveTo(ToFixedPoint(x), ToFixedPoint(y));
+ this.Canvas.lineTo(ToFixedPoint(x), ToFixedPoint(yOpen));
+ }
+ this.Canvas.stroke();
+ y = yOpen;
+ }
+ else
+ {
+ y = yOpen
+ }
+
+ this.Canvas.fillStyle = downColor;
+ if (isHScreen)
+ {
+ if (Math.abs(yClose - y) < 1)
+ {
+ this.Canvas.fillRect(ToFixedRect(y), ToFixedRect(left), 1, ToFixedRect(dataWidth)); //高度小于1,统一使用高度1
+ }
+ else
+ {
+ //宽度是负数竟然不会画, h5就可以
+ this.Canvas.fillRect(ToFixedRect(Math.min(yClose, y)), ToFixedRect(left), ToFixedRect(Math.abs(yClose - y)), ToFixedRect(dataWidth));
+ }
+ }
+ else
+ {
+ if (Math.abs(yClose - y) < 1) this.Canvas.fillRect(ToFixedRect(left), ToFixedRect(y), ToFixedRect(dataWidth), 1); //高度小于1,统一使用高度1
+ else this.Canvas.fillRect(ToFixedRect(left), ToFixedRect(y), ToFixedRect(dataWidth), ToFixedRect(yClose - y));
+ }
+
+ if (data.Open > data.Low) //下影线
+ {
+ this.Canvas.beginPath();
+ if (isHScreen)
+ {
+ this.Canvas.moveTo(ToFixedPoint(y), ToFixedPoint(x));
+ this.Canvas.lineTo(ToFixedPoint(yLow), ToFixedPoint(x));
+ }
+ else
+ {
+ this.Canvas.moveTo(ToFixedPoint(x), ToFixedPoint(y));
+ this.Canvas.lineTo(ToFixedPoint(x), ToFixedPoint(yLow));
+ }
+ this.Canvas.stroke();
+ }
+ }
+ else
+ {
+ this.Canvas.beginPath();
+ if (isHScreen)
+ {
+ this.Canvas.moveTo(yHigh, ToFixedPoint(x));
+ this.Canvas.lineTo(yLow, ToFixedPoint(x));
+ }
+ else
+ {
+ this.Canvas.moveTo(ToFixedPoint(x), yHigh);
+ this.Canvas.lineTo(ToFixedPoint(x), yLow);
+ }
+ this.Canvas.strokeStyle = downColor;
+ this.Canvas.stroke();
+ }
+ }
+ else // 平线
+ {
+ if (dataWidth >= this.MinBarWidth)
+ {
+ this.Canvas.strokeStyle = unchagneColor;
+ this.Canvas.beginPath();
+ if (data.High > data.Close) //上影线
+ {
+ if (isHScreen)
+ {
+ this.Canvas.moveTo(y, ToFixedPoint(x));
+ this.Canvas.lineTo(yOpen, ToFixedPoint(x));
+ }
+ else
+ {
+ this.Canvas.moveTo(ToFixedPoint(x), y);
+ this.Canvas.lineTo(ToFixedPoint(x), yOpen);
+ }
+ y = yOpen;
+ }
+ else
+ {
+ y = yOpen;
+ }
+
+ if (isHScreen)
+ {
+ this.Canvas.moveTo(ToFixedPoint(y), ToFixedPoint(left));
+ this.Canvas.lineTo(ToFixedPoint(y), ToFixedPoint(right));
+ }
+ else
+ {
+ this.Canvas.moveTo(ToFixedPoint(left), ToFixedPoint(y));
+ this.Canvas.lineTo(ToFixedPoint(right), ToFixedPoint(y));
+ }
+
+ if (data.Open > data.Low) //下影线
+ {
+ if (isHScreen)
+ {
+ this.Canvas.moveTo(ToFixedPoint(y), ToFixedPoint(x));
+ this.Canvas.lineTo(ToFixedPoint(yLow), ToFixedPoint(x));
+ }
+ else
+ {
+ this.Canvas.moveTo(ToFixedPoint(x), ToFixedPoint(y));
+ this.Canvas.lineTo(ToFixedPoint(x), ToFixedPoint(yLow));
+ }
+ }
+
+ this.Canvas.stroke();
+ }
+ else
+ {
+ this.Canvas.beginPath();
+ if (isHScreen)
+ {
+ this.Canvas.moveTo(yHigh, ToFixedPoint(x));
+ this.Canvas.lineTo(yLow, ToFixedPoint(x));
+ }
+ else
+ {
+ this.Canvas.moveTo(ToFixedPoint(x), yHigh);
+ this.Canvas.lineTo(ToFixedPoint(x), yLow);
+ }
+ this.Canvas.strokeStyle = unchagneColor;
+ this.Canvas.stroke();
+ }
+ }
+
+ if (this.Data.DataType == 0 && ChartData.IsDayPeriod(this.Data.Period,true)) //信息地雷
+ {
+ var infoItem = { X: x, Xleft: left, XRight: right, YMax: yHigh, YMin: yLow, DayData: data, Index: j };
+ this.DrawInfoDiv(infoItem);
+ }
+ }
+
+ this.PtMax = ptMax;
+ this.PtMin = ptMin;
+ }
+
+ this.DrawTrade = function () //交易系统
+ {
+ if (!this.TradeData) return;
+
+ var isHScreen = (this.ChartFrame.IsHScreen === true);
+ var dataWidth = this.ChartFrame.DataWidth;
+ var distanceWidth = this.ChartFrame.DistanceWidth;
+ var xOffset = this.ChartBorder.GetLeft() + distanceWidth / 2.0 + 2.0;
+ var chartright = this.ChartBorder.GetRight();
+ var xPointCount = this.ChartFrame.XPointCount;
+
+ if (isHScreen) {
+ xOffset = this.ChartBorder.GetTop() + distanceWidth / 2.0 + 2.0;
+ chartright = this.ChartBorder.GetBottom();
+ }
+
+ var sellData = this.TradeData.Sell;
+ var buyData = this.TradeData.Buy;
+ var arrowWidth = dataWidth;
+ if (arrowWidth > 10) arrowWidth = 10;
+ for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth)) {
+ var data = this.Data.Data[i];
+ if (data.Open == null || data.High == null || data.Low == null || data.Close == null) continue;
+
+ var buy = false, sell = false;
+ if (sellData && i < sellData.length) sell = sellData[i] > 0;
+ if (buyData && i < buyData.length) buy = buyData[i] > 0;
+ if (!sell && !buy) continue;
+
+ var left = xOffset;
+ var right = xOffset + dataWidth;
+ if (right > chartright) break;
+ var x = left + (right - left) / 2;
+ var yLow = this.ChartFrame.GetYFromData(data.Low);
+ var yHigh = this.ChartFrame.GetYFromData(data.High);
+ var yOpen = this.ChartFrame.GetYFromData(data.Open);
+ var yClose = this.ChartFrame.GetYFromData(data.Close);
+ var y = yHigh;
+
+ if (buy) {
+ this.Canvas.fillStyle = this.UpColor;
+ this.Canvas.strokeStyle = this.UnchagneColor;
+ this.Canvas.beginPath();
+ if (isHScreen) {
+ this.Canvas.moveTo(yLow - 1, x);
+ this.Canvas.lineTo(yLow - arrowWidth - 1, x - arrowWidth / 2);
+ this.Canvas.lineTo(yLow - arrowWidth - 1, x + arrowWidth / 2);
+ }
+ else {
+ this.Canvas.moveTo(x, yLow + 1);
+ this.Canvas.lineTo(x - arrowWidth / 2, yLow + arrowWidth + 1);
+ this.Canvas.lineTo(x + arrowWidth / 2, yLow + arrowWidth + 1);
+ }
+ this.Canvas.closePath();
+ this.Canvas.fill();
+ this.Canvas.stroke();
+ }
+
+ if (sell) {
+ this.Canvas.fillStyle = this.DownColor;
+ this.Canvas.strokeStyle = this.UnchagneColor;
+ this.Canvas.beginPath();
+ if (isHScreen) {
+ this.Canvas.moveTo(yHigh + 1, x);
+ this.Canvas.lineTo(yHigh + arrowWidth + 1, x - arrowWidth / 2);
+ this.Canvas.lineTo(yHigh + arrowWidth + 1, x + arrowWidth / 2);
+ }
+ else {
+ this.Canvas.moveTo(x, yHigh - 1);
+ this.Canvas.lineTo(x - arrowWidth / 2, yHigh - arrowWidth - 1);
+ this.Canvas.lineTo(x + arrowWidth / 2, yHigh - arrowWidth - 1);
+ }
+ this.Canvas.closePath();
+ this.Canvas.fill();
+ this.Canvas.stroke();
+ }
+ }
+ }
+
+ this.Draw = function () {
+ this.PtMax = { X: null, Y: null, Value: null, Align: 'left' }; //清空最大
+ this.PtMin = { X: null, Y: null, Value: null, Align: 'left' }; //清空最小
+ this.ChartFrame.ChartKLine = { Max: null, Min: null }; //保存K线上 显示最大最小值坐标
+
+ if (this.IsShow == false) return;
+
+ if (this.DrawType == 1) {
+ this.DrawCloseLine();
+ return;
+ }
+ else if (this.DrawType == 2) {
+ this.DrawAKLine();
+ }
+ else if (this.DrawType == 4) {
+ this.DrawCloseArea();
+ }
+ else {
+ this.DrawKBar();
+ }
+
+ this.DrawTrade();
+
+ if (this.IsShowMaxMinPrice) //标注最大值最小值
+ {
+ if (this.ChartFrame.IsHScreen === true) this.HScreenDrawMaxMinPrice(this.PtMax, this.PtMin);
+ else this.DrawMaxMinPrice(this.PtMax, this.PtMin);
+ }
+ }
+
+ this.DrawMaxMinPrice = function (ptMax, ptMin) {
+ if (ptMax.X == null || ptMax.Y == null || ptMax.Value == null) return;
+ if (ptMin.X == null || ptMin.Y == null || ptMin.Value == null) return;
+
+ var leftArrow=g_JSChartResource.KLine.MaxMin.LeftArrow;
+ var rightArrow=g_JSChartResource.KLine.MaxMin.RightArrow;
+ var highYOffset=g_JSChartResource.KLine.MaxMin.HighYOffset;
+ var lowYOffset=g_JSChartResource.KLine.MaxMin.LowYOffset;
+
+ var defaultfloatPrecision = JSCommonCoordinateData.GetfloatPrecision(this.Symbol);
+ this.Canvas.font = this.TextFont;
+ this.Canvas.fillStyle = this.TextColor;
+ this.Canvas.textAlign = ptMax.Align;
+ this.Canvas.textBaseline = 'bottom';
+ var left = ptMax.X;
+ if (IFrameSplitOperator.IsNumber(highYOffset)) ptMax.Y+=highYOffset;
+ var text = ptMax.Value.toFixed(defaultfloatPrecision);
+ if (ptMax.Align == 'left') text = leftArrow + text;
+ else text = text + rightArrow;
+ this.Canvas.fillText(text, left, ptMax.Y);
+ this.ChartFrame.ChartKLine.Max = { X: left, Y: ptMax.Y, Text: { BaseLine: 'bottom' } };
+
+ this.Canvas.textAlign = ptMin.Align;
+ this.Canvas.textBaseline = 'top';
+ var left = ptMin.X;
+ if (IFrameSplitOperator.IsNumber(lowYOffset)) ptMin.Y+=lowYOffset;
+ text = ptMin.Value.toFixed(defaultfloatPrecision);
+ if (ptMin.Align == 'left') text = leftArrow + text;
+ else text = text + rightArrow;
+ this.Canvas.fillText(text, left, ptMin.Y);
+ this.ChartFrame.ChartKLine.Min = { X: left, Y: ptMin.Y, Text: { BaseLine: 'top' } };
+ }
+
+ this.HScreenDrawMaxMinPrice = function (ptMax, ptMin) //横屏模式下显示最大最小值
+ {
+ if (ptMax.X == null || ptMax.Y == null || ptMax.Value == null) return;
+ if (ptMin.X == null || ptMin.Y == null || ptMin.Value == null) return;
+
+ var leftArrow=g_JSChartResource.KLine.MaxMin.LeftArrow;
+ var rightArrow=g_JSChartResource.KLine.MaxMin.RightArrow;
+ var highYOffset=g_JSChartResource.KLine.MaxMin.HighYOffset;
+ var lowYOffset=g_JSChartResource.KLine.MaxMin.LowYOffset;
+
+ var defaultfloatPrecision = JSCommonCoordinateData.GetfloatPrecision(this.Symbol);
+ var xText = ptMax.Y;
+ var yText = ptMax.X;
+ if (IFrameSplitOperator.IsNumber(highYOffset)) xText+=highYOffset;
+ this.Canvas.save();
+ this.Canvas.translate(xText, yText);
+ this.Canvas.rotate(90 * Math.PI / 180);
+
+ this.Canvas.font = this.TextFont;
+ this.Canvas.fillStyle = this.TextColor;
+ this.Canvas.textAlign = ptMax.Align;
+ this.Canvas.textBaseline = 'bottom';
+ var text = ptMax.Value.toFixed(defaultfloatPrecision);
+ if (ptMax.Align == 'left') text = leftArrow + text;
+ else text = text + rightArrow;
+ this.Canvas.fillText(text, 0, 0);
+ this.Canvas.restore();
+
+
+ var xText = ptMin.Y;
+ var yText = ptMin.X;
+ if (IFrameSplitOperator.IsNumber(lowYOffset)) xText+=lowYOffset;
+ this.Canvas.save();
+ this.Canvas.translate(xText, yText);
+ this.Canvas.rotate(90 * Math.PI / 180);
+
+ this.Canvas.font = this.TextFont;
+ this.Canvas.fillStyle = this.TextColor;
+ this.Canvas.textAlign = ptMin.Align;
+ this.Canvas.textBaseline = 'top';
+ var text = ptMin.Value.toFixed(defaultfloatPrecision);
+ if (ptMin.Align == 'left') text = leftArrow + text;
+ else text = text + rightArrow;
+ this.Canvas.fillText(text, 0, 0);
+ this.Canvas.restore();
+ }
+
+ //画某一天的信息地雷 画在底部
+ this.DrawInfoDiv = function (item) {
+ if (!this.InfoData || this.InfoData.length <= 0) return;
+
+ var dataWidth = this.ChartFrame.DataWidth;
+ var distanceWidth = this.ChartFrame.DistanceWidth;
+
+ var infoData = this.InfoData.get(item.DayData.Date.toString());
+ if (!infoData || infoData.Data.length <= 0) return;
+ var bHScreen = (this.ChartFrame.IsHScreen === true);
+ if (this.InfoDrawType === 1) {
+ this.Canvas.font = this.GetDynamicFont(dataWidth);
+ this.Canvas.fillStyle = this.InfoPointColor2;
+ this.Canvas.textAlign = 'center';
+ this.Canvas.textBaseline = 'top';
+ if (bHScreen) {
+ var xText = item.YMin;
+ var yText = item.X;
+ this.Canvas.save();
+ this.Canvas.translate(xText, yText);
+ this.Canvas.rotate(90 * Math.PI / 180);
+ this.Canvas.fillText('▲', 0, 0);
+ this.Canvas.restore();
+ }
+ else {
+ var left = ToFixedPoint(item.X);
+ this.Canvas.fillText('▲', left, item.YMin);
+ }
+ }
+ else {
+ var dataWidth = this.ChartFrame.DataWidth;
+ var radius = dataWidth / 2;
+ if (radius > 3) radius = 3;
+ var x = item.X;
+ var y = this.ChartFrame.ChartBorder.GetBottom() - 2 - radius;
+ if (bHScreen) y = this.ChartFrame.ChartBorder.GetLeft() + 2 + radius;
+
+ this.Canvas.fillStyle = this.InfoPointColor;
+ this.Canvas.beginPath();
+ if (bHScreen) this.Canvas.arc(y, x, radius, 0, Math.PI * 2, true);
+ else this.Canvas.arc(ToFixedPoint(x), y, radius, 0, Math.PI * 2, true);
+ this.Canvas.closePath();
+ this.Canvas.fill();
+ }
+ }
+
+ this.GetTooltipData = function (x, y, tooltip) {
+ return false;
+ }
+
+ this.GetMaxMin = function () //计算当天显示数据的最大最小值
+ {
+ var xPointCount = this.ChartFrame.XPointCount;
+ var range = {};
+ range.Max = null;
+ range.Min = null;
+
+ if (this.IsShow == false) return range;
+
+ if (this.DrawType==1 || this.DrawType==4 ) // 1=收盘价线 4=收盘价面积图
+ {
+ for(var i=this.Data.DataOffset,j=0;idata.Close) range.Min=data.Close;
+ }
+ }
+ else
+ {
+ for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j)
+ {
+ var data = this.Data.Data[i];
+ if (data.Open == null || data.High == null || data.Low == null || data.Close == null) continue;
+
+ if (range.Max == null) range.Max = data.High;
+ if (range.Min == null) range.Min = data.Low;
+
+ if (range.Max < data.High) range.Max = data.High;
+ if (range.Min > data.Low) range.Min = data.Low;
+ }
+
+ }
+
+ return range;
+ }
+}
+
+
+
+/*
+ 文字输出 支持横屏
+ 数组不为null的数据中输出 this.Text文本
+*/
+function ChartSingleText()
+{
+ this.newMethod = IChartPainting; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.Color = "rgb(255,193,37)"; //线段颜色
+ this.TextFont = "14px 微软雅黑"; //字体
+ this.Text;
+ this.TextAlign = 'left';
+ this.Direction = 0; //0=middle 1=bottom 2=top
+ this.YOffset = 0;
+ this.Position; //指定输出位置
+
+ this.TextSize=
+ {
+ Max: g_JSChartResource.DRAWICON.Text.MaxSize, Min:g_JSChartResource.DRAWICON.Text.MinSize, //字体的最大最小值
+ Zoom:{ Type:g_JSChartResource.DRAWICON.Text.Zoom.Type , Value:g_JSChartResource.DRAWICON.Text.Zoom.Value }, //放大倍数
+ FontName:g_JSChartResource.DRAWICON.Text.FontName
+ }
+
+ this.ReloadResource=function(resource)
+ {
+ if (this.Name=="DRAWTEXT")
+ {
+ this.TextSize=
+ {
+ Max: g_JSChartResource.DRAWTEXT.MaxSize, Min:g_JSChartResource.DRAWTEXT.MinSize, //字体的最大最小值
+ Zoom:{ Type:g_JSChartResource.DRAWTEXT.Zoom.Type , Value:g_JSChartResource.DRAWTEXT.Zoom.Value }, //放大倍数
+ FontName:g_JSChartResource.DRAWTEXT.FontName
+ }
+ }
+ else if (this.Name=="DRAWNUMBER")
+ {
+ this.TextSize=
+ {
+ Max: g_JSChartResource.DRAWNUMBER.MaxSize, Min:g_JSChartResource.DRAWNUMBER.MinSize, //字体的最大最小值
+ Zoom:{ Type:g_JSChartResource.DRAWNUMBER.Zoom.Type , Value:g_JSChartResource.DRAWNUMBER.Zoom.Value }, //放大倍数
+ FontName:g_JSChartResource.DRAWNUMBER.FontName
+ }
+ }
+ }
+
+ this.Draw = function ()
+ {
+ if (!this.IsShow || this.ChartFrame.IsMinSize) return;
+
+ if (this.NotSupportMessage)
+ {
+ this.DrawNotSupportmessage();
+ return;
+ }
+
+ if (this.Position)
+ {
+ this.DrawPosition();
+ return;
+ }
+
+ if (!this.Data || !this.Data.Data) return;
+
+ var isHScreen = (this.ChartFrame.IsHScreen === true)
+ var dataWidth = this.ChartFrame.DataWidth;
+ var distanceWidth = this.ChartFrame.DistanceWidth;
+ var chartright = this.ChartBorder.GetRight();
+ var top = this.ChartBorder.GetTopEx();
+ var bottom = this.ChartBorder.GetBottomEx();
+ if (isHScreen)
+ {
+ chartright = this.ChartBorder.GetBottom();
+ top = this.ChartBorder.GetRightEx();
+ bottom = this.ChartBorder.GetLeftEx();
+ }
+ var xPointCount = this.ChartFrame.XPointCount;
+
+ var isArrayText = Array.isArray(this.Text);
+ var text;
+ if (this.Direction == 1) this.Canvas.textBaseline = 'bottom';
+ else if (this.Direction == 2) this.Canvas.textBaseline = 'top';
+ else this.Canvas.textBaseline = 'middle';
+ this.TextFont = this.GetDynamicFontEx(dataWidth,distanceWidth,this.TextSize.Max,this.TextSize.Min,this.TextSize.Zoom,this.TextSize.FontName);
+ for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j)
+ {
+ var value = this.Data.Data[i];
+ if (value == null) continue;
+ var x = this.ChartFrame.GetXFromIndex(j);
+ var y = this.ChartFrame.GetYFromData(value);
+
+ if (x > chartright) break;
+
+ this.Canvas.textAlign = this.TextAlign;
+ this.Canvas.fillStyle = this.Color;
+ this.Canvas.font = this.TextFont;
+
+ if (this.YOffset > 0 && this.Direction > 0)
+ {
+ var yPrice = y;
+
+ this.Canvas.save();
+ this.Canvas.setLineDash([5, 10]);
+ this.Canvas.strokeStyle = this.Color;
+ this.Canvas.beginPath();
+ if (isHScreen)
+ {
+ if (this.Direction == 1)
+ {
+ y = top - this.YOffset;
+ yPrice += 5;
+ }
+ else
+ {
+ y = bottom + this.YOffset;
+ yPrice -= 5;
+ }
+ this.Canvas.moveTo(ToFixedPoint(yPrice), ToFixedPoint(x));
+ this.Canvas.lineTo(ToFixedPoint(y), ToFixedPoint(x));
+ }
+ else
+ {
+ if (this.Direction == 1)
+ {
+ y = top + this.YOffset;
+ yPrice += 5;
+ }
+ else
+ {
+ y = bottom - this.YOffset;
+ yPrice -= 5;
+ }
+ this.Canvas.moveTo(ToFixedPoint(x), ToFixedPoint(yPrice));
+ this.Canvas.lineTo(ToFixedPoint(x), ToFixedPoint(y));
+ }
+
+ this.Canvas.stroke();
+ this.Canvas.restore();
+ }
+
+ if (isArrayText)
+ {
+ text = this.Text[i];
+ if (!text) continue;
+ if (isHScreen)
+ {
+ if (this.Name=='DRAWNUMBER')
+ {
+ if (this.Direction==1) y+=g_JSChartResource.DRAWABOVE.YOffset;
+ else if (this.Direction==2) y-=4;
+ }
+ }
+ else
+ {
+ if (this.Name=='DRAWNUMBER')
+ {
+ if (this.Direction==1) y-=g_JSChartResource.DRAWABOVE.YOffset;
+ else if (this.Direction==2) y+=4;
+ }
+ }
+
+ this.DrawText(text, x, y, isHScreen);
+ }
+ else
+ {
+ this.DrawText(this.Text, x, y, isHScreen);
+ }
+ }
+ }
+
+ this.DrawPosition=function() //绘制在指定位置上
+ {
+ if (!this.Text) return;
+ var isHScreen=(this.ChartFrame.IsHScreen===true)
+ if (isHScreen)
+ {
+ var y=this.ChartBorder.GetRightEx()-this.ChartBorder.GetWidthEx()*this.Position.Y;
+ var x=this.ChartBorder.GetTop()+this.ChartBorder.GetHeight()*this.Position.X;
+ }
+ else
+ {
+ var x=this.ChartBorder.GetLeft()+this.ChartBorder.GetWidth()*this.Position.X;
+ var y=this.ChartBorder.GetTopEx()+this.ChartBorder.GetHeight()*this.Position.Y;
+ }
+
+ this.Canvas.fillStyle=this.Color;
+
+ //TYPE:0为左对齐,1为右对齐.
+ if (this.Position.Type==0) this.Canvas.textAlign='left';
+ else if (this.Position.Type==1) this.Canvas.textAlign='right';
+ else this.Canvas.textAlign='center';
+
+ if (this.Direction==1) this.Canvas.textBaseline='bottom';
+ else if (this.Direction==2) this.Canvas.textBaseline='top';
+ else this.Canvas.textBaseline='middle';
+
+ this.DrawText(this.Text,x,y,isHScreen);
+ }
+
+ this.DrawText = function (text, x, y, isHScreen)
+ {
+ if (isHScreen)
+ {
+ this.Canvas.save();
+ this.Canvas.translate(y, x);
+ this.Canvas.rotate(90 * Math.PI / 180);
+ this.Canvas.fillText(text, 0, 0);
+ this.Canvas.restore();
+ }
+ else
+ {
+ this.Canvas.fillText(text, x, y);
+ }
+ }
+}
+
+
+//线段
+function ChartLine()
+{
+ this.newMethod = IChartPainting; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.ClassName ='ChartLine';
+ this.Color = "rgb(255,193,37)"; //线段颜色
+ this.LineWidth; //线段宽度
+ this.DrawType = 0; //画图方式 0=无效数平滑 1=无效数不画断开
+ this.IsDotLine = false; //虚线
+
+ this.Draw = function ()
+ {
+ if (!this.IsShow || this.ChartFrame.IsMinSize) return;
+ if (this.NotSupportMessage)
+ {
+ this.DrawNotSupportmessage();
+ return;
+ }
+
+ if (!this.Data || !this.Data.Data) return;
+
+ switch (this.DrawType)
+ {
+ case 0:
+ return this.DrawLine();
+ case 1:
+ return this.DrawStraightLine();
+ }
+ }
+
+ this.DrawLine = function ()
+ {
+ var bHScreen = (this.ChartFrame.IsHScreen === true);
+ var dataWidth = this.ChartFrame.DataWidth;
+ var distanceWidth = this.ChartFrame.DistanceWidth;
+ var chartright = this.ChartBorder.GetRight();
+ if (bHScreen) chartright = this.ChartBorder.GetBottom();
+ var xPointCount = this.ChartFrame.XPointCount;
+
+ this.Canvas.save();
+ if (this.LineWidth > 0) this.Canvas.lineWidth = this.LineWidth;
+ var bFirstPoint = true;
+ var drawCount = 0;
+ for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j)
+ {
+ var value = this.Data.Data[i];
+ if (value == null) continue;
+
+ var x = this.ChartFrame.GetXFromIndex(j);
+ var y = this.GetYFromData(value);
+
+ if (x > chartright) break;
+
+ if (bFirstPoint)
+ {
+ this.Canvas.strokeStyle = this.Color;
+ this.Canvas.beginPath();
+ if (bHScreen) this.Canvas.moveTo(y, x); //横屏坐标轴对调
+ else this.Canvas.moveTo(x, y);
+ bFirstPoint = false;
+ }
+ else
+ {
+ if (bHScreen) this.Canvas.lineTo(y, x);
+ else this.Canvas.lineTo(x, y);
+ }
+
+ ++drawCount;
+ }
+
+ if (drawCount > 0) this.Canvas.stroke();
+ this.Canvas.restore();
+ }
+
+ //无效数不画
+ this.DrawStraightLine = function ()
+ {
+ var bHScreen = (this.ChartFrame.IsHScreen === true);
+ var isMinute=this.IsMinuteFrame();
+ var dataWidth = this.ChartFrame.DataWidth;
+ var distanceWidth = this.ChartFrame.DistanceWidth;
+ var xOffset=this.ChartBorder.GetLeft()+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin;
+ var chartright = this.ChartBorder.GetRight();
+ if (bHScreen) chartright = this.ChartBorder.GetBottom();
+ if (bHScreen) xOffset=this.ChartBorder.GetTop()+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin;
+ var xPointCount = this.ChartFrame.XPointCount;
+
+ this.Canvas.save();
+ if (this.LineWidth > 0) this.Canvas.lineWidth = this.LineWidth;
+ this.Canvas.strokeStyle = this.Color;
+ if (this.IsDotLine) this.Canvas.setLineDash([3, 5]); //画虚线
+
+ var bFirstPoint = true;
+ var drawCount = 0;
+ for(var i=this.Data.DataOffset,j=0;i 0) this.Canvas.stroke();
+ bFirstPoint = true;
+ drawCount = 0;
+ continue;
+ }
+
+ if (isMinute)
+ {
+ var x = this.ChartFrame.GetXFromIndex(j);
+ }
+ else
+ {
+ var left=xOffset;
+ var right=xOffset+dataWidth;
+ if (right>chartright) break;
+ var x=left+(right-left)/2;
+ }
+
+
+ var y = this.GetYFromData(value);
+
+ if (x > chartright) break;
+
+ if (bFirstPoint)
+ {
+ this.Canvas.beginPath();
+ if (bHScreen) this.Canvas.moveTo(y, x); //横屏坐标轴对调
+ else this.Canvas.moveTo(x, y);
+ bFirstPoint = false;
+ }
+ else
+ {
+ if (bHScreen) this.Canvas.lineTo(y, x);
+ else this.Canvas.lineTo(x, y);
+ }
+
+ ++drawCount;
+ }
+
+ if (drawCount > 0) this.Canvas.stroke();
+ this.Canvas.restore();
+ }
+
+ this.GetYFromData = function (value)
+ {
+ return this.ChartFrame.GetYFromData(value);
+ }
+}
+
+//子线段
+function ChartSubLine()
+{
+ this.newMethod = ChartLine; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.ClassName = 'ChartSubLine'; //类名
+ this.Color = "rgb(255,193,37)"; //线段颜色
+ this.LineWidth; //线段宽度
+ this.DrawType = 0; //画图方式 0=无效数平滑 1=无效数不画断开
+ this.IsDotLine = false; //虚线
+
+ this.SubFrame = { Max: null, Min: null };
+
+ this.Draw = function ()
+ {
+ if (!this.IsShow) return;
+ if (!this.Data || !this.Data.Data) return;
+
+ this.CalculateDataMaxMin();
+
+ switch (this.DrawType)
+ {
+ case 0:
+ return this.DrawLine();
+ case 1:
+ return this.DrawStraightLine();
+ }
+ }
+
+ this.GetYFromData = function (value)
+ {
+ var bHScreen = (this.ChartFrame.IsHScreen === true);
+
+ if (bHScreen)
+ {
+ if (value <= this.SubFrame.Min) return this.ChartBorder.GetLeftEx();
+ if (value >= this.SubFrame.Max) return this.ChartBorder.GetRightEx();
+
+ var width = this.ChartBorder.GetWidthEx() * (value - this.SubFrame.Min) / (this.SubFrame.Max - this.SubFrame.Min);
+ return this.ChartBorder.GetLeftEx() + width;
+ }
+ else
+ {
+ if (value <= this.SubFrame.Min) return this.ChartBorder.GetBottomEx();
+ if (value >= this.SubFrame.Max) return this.ChartBorder.GetTopEx();
+
+ var height = this.ChartBorder.GetHeightEx() * (value - this.SubFrame.Min) / (this.SubFrame.Max - this.SubFrame.Min);
+ return this.ChartBorder.GetBottomEx() - height;
+ }
+ }
+
+ this.CalculateDataMaxMin = function ()
+ {
+ this.SubFrame = { Max: null, Min: null };
+
+ var bHScreen = (this.ChartFrame.IsHScreen === true);
+ var chartright = this.ChartBorder.GetRight();
+ if (bHScreen) chartright = this.ChartBorder.GetBottom();
+ var xPointCount = this.ChartFrame.XPointCount;
+ for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j)
+ {
+ var value = this.Data.Data[i];
+ if (value == null) continue;
+
+ var x = this.ChartFrame.GetXFromIndex(j);
+ if (x > chartright) break;
+
+ if (this.SubFrame.Min == null || this.SubFrame.Min > value) this.SubFrame.Min = value;
+ if (this.SubFrame.Max == null || this.SubFrame.Max < value) this.SubFrame.Max = value;
+ }
+ }
+
+ this.GetMaxMin = function () //数据不参与坐标轴最大最小值计算
+ {
+ var range = { Min: null, Max: null };
+ return range;
+ }
+}
+
+//POINTDOT 圆点 支持横屏
+function ChartPointDot()
+{
+ this.newMethod = IChartPainting; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.Color = "rgb(255,193,37)"; //线段颜色
+ this.Radius = 1; //点半径
+ this.ClassName = 'ChartPointDot';
+
+ this.Draw = function ()
+ {
+ if (!this.IsShow || this.ChartFrame.IsMinSize) return;
+
+ if (this.NotSupportMessage)
+ {
+ this.DrawNotSupportmessage();
+ return;
+ }
+
+ if (!this.Data || !this.Data.Data) return;
+
+ var bHScreen = (this.ChartFrame.IsHScreen === true);
+ var dataWidth = this.ChartFrame.DataWidth;
+ var distanceWidth = this.ChartFrame.DistanceWidth;
+ var chartright = this.ChartBorder.GetRight();
+ if (bHScreen === true) chartright = this.ChartBorder.GetBottom();
+ var xPointCount = this.ChartFrame.XPointCount;
+
+ this.Canvas.save();
+ this.Canvas.fillStyle = this.Color;
+ for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j)
+ {
+ var value = this.Data.Data[i];
+ if (value == null) continue;
+
+ var x = this.ChartFrame.GetXFromIndex(j);
+ var y = this.ChartFrame.GetYFromData(value);
+
+ if (x > chartright) break;
+
+ this.Canvas.beginPath();
+ if (bHScreen) this.Canvas.arc(y, x, this.Radius, 0, Math.PI * 2, true);
+ else this.Canvas.arc(x, y, this.Radius, 0, Math.PI * 2, true);
+ this.Canvas.closePath();
+ this.Canvas.fill();
+ }
+
+ this.Canvas.restore();
+ }
+}
+
+//通达信语法 STICK 支持横屏
+function ChartStick()
+{
+ this.newMethod = IChartPainting; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.Color = "rgb(255,193,37)"; //线段颜色
+ this.LineWidth; //线段宽度
+ this.ClassName = 'ChartStick';
+
+ this.DrawLine = function ()
+ {
+ if (this.ChartFrame.IsMinSize) return;
+ if (!this.Data || !this.Data.Data) return;
+
+ var isHScreen = (this.ChartFrame.IsHScreen === true);
+ var dataWidth = this.ChartFrame.DataWidth;
+ var distanceWidth = this.ChartFrame.DistanceWidth;
+ var chartright = this.ChartBorder.GetRight();
+ if (isHScreen === true) chartright = this.ChartBorder.GetBottom();
+ var xPointCount = this.ChartFrame.XPointCount;
+
+ this.Canvas.save();
+ if (this.LineWidth > 0) this.Canvas.lineWidth = this.LineWidth;
+ var bFirstPoint = true;
+ var drawCount = 0;
+ for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j)
+ {
+ var value = this.Data.Data[i];
+ if (value == null) continue;
+
+ var x = this.ChartFrame.GetXFromIndex(j);
+ var y = this.ChartFrame.GetYFromData(value);
+
+ if (x > chartright) break;
+
+ if (bFirstPoint)
+ {
+ this.Canvas.strokeStyle = this.Color;
+ this.Canvas.beginPath();
+ if (isHScreen) this.Canvas.moveTo(y, x);
+ else this.Canvas.moveTo(x, y);
+ bFirstPoint = false;
+ }
+ else
+ {
+ if (isHScreen) this.Canvas.lineTo(y, x);
+ else this.Canvas.lineTo(x, y);
+ }
+
+ ++drawCount;
+ }
+
+ if (drawCount > 0) this.Canvas.stroke();
+ this.Canvas.restore();
+ }
+
+ this.DrawStick = function ()
+ {
+ if (!this.Data || !this.Data.Data) return;
+ var bHScreen = (this.ChartFrame.IsHScreen === true);
+ var chartright = this.ChartBorder.GetRight();
+ if (bHScreen) chartright = this.ChartBorder.GetBottom();
+ var xPointCount = this.ChartFrame.XPointCount;
+ var yBottom = this.ChartBorder.GetBottom();
+ var xLeft = this.ChartBorder.GetLeft();
+
+ this.Canvas.save();
+ this.Canvas.strokeStyle = this.Color;
+ if (this.LineWidth) this.Canvas.lineWidth = this.LineWidth;
+ for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j)
+ {
+ var value = this.Data.Data[i];
+ if (value == null) continue;
+
+ var x = this.ChartFrame.GetXFromIndex(j);
+ var y = this.ChartFrame.GetYFromData(value);
+
+ if (x > chartright) break;
+
+ this.Canvas.beginPath();
+ if (bHScreen)
+ {
+ this.Canvas.moveTo(xLeft, x);
+ this.Canvas.lineTo(y, x);
+ this.Canvas.stroke();
+ }
+ else
+ {
+ var xFix = parseInt(x.toString()) + 0.5;
+ this.Canvas.moveTo(xFix, y);
+ this.Canvas.lineTo(xFix, yBottom);
+ }
+ this.Canvas.stroke();
+ }
+ this.Canvas.restore();
+ }
+
+ this.Draw = function ()
+ {
+ if (!this.IsShow) return;
+
+ if (this.NotSupportMessage)
+ {
+ this.DrawNotSupportmessage();
+ return;
+ }
+
+ this.DrawStick();
+ }
+}
+
+//通达信语法 LINESTICK 支持横屏
+function ChartLineStick()
+{
+ this.newMethod = ChartStick; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.ClassName = 'ChartLineStick';
+
+ this.Draw = function ()
+ {
+ if (!this.IsShow || this.ChartFrame.IsMinSize) return;
+
+ if (this.NotSupportMessage)
+ {
+ this.DrawNotSupportmessage();
+ return;
+ }
+
+ this.DrawStick();
+ this.DrawLine();
+ }
+}
+
+//柱子 支持横屏
+function ChartStickLine()
+{
+ this.newMethod = IChartPainting; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.ClassName ='ChartStickLine';
+ this.Color = "rgb(255,193,37)"; //线段颜色
+ this.LineWidth = 2; //线段宽度
+ this.BarType = 0; //柱子类型 0=实心 1=空心
+ this.MinBarWidth=g_JSChartResource.MinKLineBarWidth; //最小的柱子宽度
+
+ this.Draw = function ()
+ {
+ if (this.ChartFrame.IsMinSize) return;
+ if (this.NotSupportMessage)
+ {
+ this.DrawNotSupportmessage();
+ return;
+ }
+
+ if (!this.Data || !this.Data.Data) return;
+
+ var isHScreen = (this.ChartFrame.IsHScreen === true);
+ var dataWidth = this.ChartFrame.DataWidth;
+ var distanceWidth = this.ChartFrame.DistanceWidth;
+ var chartright = this.ChartBorder.GetRight();
+ if (isHScreen) chartright = this.ChartBorder.GetBottom();
+ var xPointCount = this.ChartFrame.XPointCount;
+ var xOffset = this.ChartBorder.GetLeft() + distanceWidth / 2.0 + 2.0;
+ if (isHScreen) xOffset = this.ChartBorder.GetTop() + distanceWidth / 2.0 + 2.0;
+
+ var isMinute=this.IsMinuteFrame();
+
+ this.Canvas.save();
+ var bFillBar = false;
+ var bFillKLine = false;
+
+ if (isMinute)
+ {
+ if (this.LineWidth>1) this.Canvas.lineWidth=2;
+ else this.Canvas.lineWidth=1;
+ this.Canvas.strokeStyle=this.Color;
+ }
+ else if (this.LineWidth==50)
+ {
+ if (dataWidth >= this.MinBarWidth)
+ {
+ bFillKLine = true;
+ this.Canvas.fillStyle = this.Color;
+ this.Canvas.strokeStyle = this.Color;
+ }
+ else //太细了 画竖线
+ {
+ this.Canvas.lineWidth = 1;
+ this.Canvas.strokeStyle = this.Color;
+ }
+ }
+ else if (this.LineWidth < 100)
+ {
+ var LineWidth = this.LineWidth;
+ if (dataWidth <= 4) LineWidth = 1;
+ else if (dataWidth < LineWidth) LineWidth = parseInt(dataWidth);
+ this.Canvas.lineWidth = LineWidth;
+ this.Canvas.strokeStyle = this.Color;
+ }
+ else
+ {
+ bFillBar = true;
+ this.Canvas.fillStyle = this.Color;
+ var fixedWidth = 2;
+ }
+
+ for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth))
+ {
+ var value = this.Data.Data[i];
+ if (value == null) continue;
+
+ var price = value.Value;
+ var price2 = value.Value2;
+ if (price2 == null) price2 = 0;
+
+ var x = this.ChartFrame.GetXFromIndex(j);
+ var y = this.ChartFrame.GetYFromData(price);
+ var y2 = this.ChartFrame.GetYFromData(price2);
+
+ if (x > chartright) break;
+
+ if (bFillBar)
+ {
+ var left = xOffset - fixedWidth;
+ if (isHScreen)
+ {
+ this.Canvas.fillRect(Math.min(y, y2), left, Math.abs(y - y2), dataWidth + distanceWidth + fixedWidth * 2);
+ }
+ else
+ {
+ var barWidth = dataWidth + distanceWidth + fixedWidth * 2;
+ if (left + barWidth > chartright) barWidth = chartright - left; //不要超过右边框子
+ this.Canvas.fillRect(left, ToFixedRect(Math.min(y, y2)), barWidth, ToFixedRect(Math.abs(y - y2)));
+ }
+ }
+ else if (bFillKLine)
+ {
+ if (this.BarType == 1) //实心
+ {
+ if (isHScreen)
+ {
+ this.Canvas.beginPath();
+ this.Canvas.fillRect(ToFixedRect(Math.min(y, y2)), ToFixedRect(xOffset), ToFixedRect(Math.abs(y - y2)), ToFixedRect(dataWidth));
+ this.Canvas.stroke();
+ }
+ else
+ {
+ this.Canvas.beginPath();
+ this.Canvas.rect(ToFixedRect(xOffset), ToFixedRect(Math.min(y, y2)), ToFixedRect(dataWidth), ToFixedRect(Math.abs(y - y2)));
+ this.Canvas.stroke();
+ }
+ }
+ else
+ {
+ if (isHScreen)
+ this.Canvas.fillRect(ToFixedRect(Math.min(y, y2)), ToFixedRect(xOffset), ToFixedRect(Math.abs(y - y2)), ToFixedRect(dataWidth));
+ else
+ this.Canvas.fillRect(ToFixedRect(xOffset), ToFixedRect(Math.min(y, y2)), ToFixedRect(dataWidth), ToFixedRect(Math.abs(y - y2)));
+ }
+ }
+ else
+ {
+ if (isHScreen)
+ {
+ this.Canvas.beginPath();
+ this.Canvas.moveTo(y, ToFixedPoint(x));
+ this.Canvas.lineTo(y2, ToFixedPoint(x));
+ this.Canvas.stroke();
+ }
+ else
+ {
+ var xFix = parseInt(x.toString()) + 0.5;
+ this.Canvas.beginPath();
+ this.Canvas.moveTo(xFix, y);
+ this.Canvas.lineTo(xFix, y2);
+ this.Canvas.stroke();
+ }
+ }
+ }
+
+ this.Canvas.restore();
+ }
+
+ this.GetMaxMin = function ()
+ {
+ var xPointCount = this.ChartFrame.XPointCount;
+ var range = {};
+ range.Min = null;
+ range.Max = null;
+
+ if (!this.Data || !this.Data.Data) return range;
+
+ for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j)
+ {
+ var data = this.Data.Data[i];
+ if (data == null) continue;
+ var value2 = data.Value2;
+ if (value2 == null) value2 = 0;
+ if (data == null || isNaN(data.Value) || isNaN(value2)) continue;
+
+ var valueMax = Math.max(data.Value, value2);
+ var valueMin = Math.min(data.Value, value2);
+
+ if (range.Max == null) range.Max = valueMax;
+ if (range.Min == null) range.Min = valueMin;
+
+ if (range.Max < valueMax) range.Max = valueMax;
+ if (range.Min > valueMin) range.Min = valueMin;
+ }
+
+ return range;
+ }
+}
+
+//画矩形
+function ChartRectangle()
+{
+ this.newMethod = IChartPainting; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.ClassName ='ChartRectangle';
+ this.Color = [];
+ this.Rect;
+ this.BorderColor = g_JSChartResource.FrameBorderPen;
+
+ this.Draw = function ()
+ {
+ if (!this.IsShow || this.ChartFrame.IsMinSize) return;
+ if (!this.Color || !this.Rect) return;
+ if (this.Color.length <= 0) return;
+
+ this.Canvas.strokeStyle = this.BorderColor;
+ var bFill = false;
+ if (this.Color.length == 2)
+ {
+ /* TODO 渐变下次做吧
+ if (this.ColorAngle==0)
+ {
+ var ptStart={ X:this.ChartBorder.GetLeft(), Y:this.ChartBorder.GetTopEx() };
+ var ptEnd={ X:this.ChartBorder.GetLeft(), Y:this.ChartBorder.GetBottomEx() };
+ }
+ else
+ {
+ var ptStart={ X:this.ChartBorder.GetLeft(), Y:this.ChartBorder.GetTopEx() };
+ var ptEnd={ X:this.ChartBorder.GetRight(), Y:this.ChartBorder.GetTopEx() };
+ }
+
+ let gradient = this.Canvas.createLinearGradient(ptStart.X,ptStart.Y, ptEnd.X,ptEnd.Y);
+ gradient.addColorStop(0, this.Color[0]);
+ gradient.addColorStop(1, this.Color[1]);
+ this.Canvas.fillStyle=gradient;
+ */
+
+ this.Canvas.fillStyle = this.Color[0];
+ bFill = true;
+ }
+ else if (this.Color.length == 1)
+ {
+ if (this.Color[0])
+ {
+ this.Canvas.fillStyle = this.Color[0];
+ bFill = true;
+ }
+ }
+ else
+ {
+ return;
+ }
+
+ var chartWidth = this.ChartBorder.GetWidth();
+ var chartHeight = this.ChartBorder.GetHeightEx();
+ var left = this.Rect.Left / 1000 * chartWidth;
+ var top = this.Rect.Top / 1000 * chartHeight;
+ var right = this.Rect.Right / 1000 * chartWidth;
+ var bottom = this.Rect.Bottom / 1000 * chartHeight;
+
+ left = this.ChartBorder.GetLeft() + left
+ top = this.ChartBorder.GetTopEx() + top;
+ right = this.ChartBorder.GetLeft() + right;
+ bottom = this.ChartBorder.GetTopEx() + bottom;
+ var width = Math.abs(left - right);
+ var height = Math.abs(top - bottom);
+ if (bFill) this.Canvas.fillRect(left, top, width, height);
+ this.Canvas.rect(ToFixedPoint(left), ToFixedPoint(top), ToFixedRect(width), ToFixedRect(height));
+ this.Canvas.stroke();
+ }
+}
+
+//K线叠加
+function ChartOverlayKLine()
+{
+ this.newMethod = IChartPainting; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.Color = "rgb(65,105,225)";
+ this.MainData; //主图K线数据
+ this.SourceData; //叠加的原始数据
+ this.Name = "ChartOverlayKLine";
+ this.Title;
+ this.DrawType = 0;
+ this.ClassName ='ChartOverlayKLine';
+ this.CustomDrawType = null; //图形类型
+
+ this.SetOption = function (option)
+ {
+ if (!option) return;
+ if (IFrameSplitOperator.IsNumber(option.DrawType)) this.CustomDrawType = option.DrawType;
+ }
+
+ this.DrawKBar = function (firstOpen) //firstOpen 当前屏第1个显示数据
+ {
+ var isHScreen = (this.ChartFrame.IsHScreen === true);
+ var dataWidth = this.ChartFrame.DataWidth;
+ var distanceWidth = this.ChartFrame.DistanceWidth;
+ var xOffset = this.ChartBorder.GetLeft() + distanceWidth / 2.0 + 2.0;
+ if (isHScreen) xOffset = this.ChartBorder.GetTop() + distanceWidth / 2.0 + 2.0;
+ var chartright = this.ChartBorder.GetRight();
+ if (isHScreen) chartright = this.ChartBorder.GetBottom();
+ var xPointCount = this.ChartFrame.XPointCount;
+
+ var isFristDraw = true;
+ var firstOverlayOpen = null;
+
+ for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth))
+ {
+ var data = this.Data.Data[i];
+ if (!data || data.Open == null || data.High == null || data.Low == null || data.Close == null) continue;
+
+ if (firstOverlayOpen == null) firstOverlayOpen = data.Open;
+
+ if (isFristDraw)
+ {
+ this.Canvas.strokeStyle = this.Color;
+ this.Canvas.fillStyle = this.Color;
+ this.Canvas.beginPath();
+ isFristDraw = false;
+ }
+
+ var left = xOffset;
+ var right = xOffset + dataWidth;
+ if (right > chartright) break;
+ var x = left + (right - left) / 2;
+ var yLow = this.ChartFrame.GetYFromData(data.Low / firstOverlayOpen * firstOpen);
+ var yHigh = this.ChartFrame.GetYFromData(data.High / firstOverlayOpen * firstOpen);
+ var yOpen = this.ChartFrame.GetYFromData(data.Open / firstOverlayOpen * firstOpen);
+ var yClose = this.ChartFrame.GetYFromData(data.Close / firstOverlayOpen * firstOpen);
+ var y = yHigh;
+
+ if (data.Open < data.Close) //阳线
+ {
+ if (dataWidth >= 4)
+ {
+ if (data.High > data.Close) //上影线
+ {
+ if (isHScreen)
+ {
+ this.Canvas.moveTo(ToFixedPoint(y), ToFixedPoint(x));
+ this.Canvas.lineTo(ToFixedPoint(this.DrawType == 3 ? Math.max(yClose, yOpen) : yClose), ToFixedPoint(x));
+ }
+ else
+ {
+ this.Canvas.moveTo(ToFixedPoint(x), ToFixedPoint(y));
+ this.Canvas.lineTo(ToFixedPoint(x), ToFixedPoint(this.DrawType == 3 ? Math.min(yClose, yOpen) : yClose));
+ }
+ y = yClose;
+ }
+ else
+ {
+ y = yClose;
+ }
+
+ if (isHScreen) {
+ if (Math.abs(yOpen - y) < 1)
+ {
+ this.Canvas.fillRect(ToFixedRect(y), ToFixedRect(left), 1, ToFixedRect(dataWidth)); //高度小于1,统一使用高度1
+ }
+ else
+ {
+ if (this.DrawType == 3) this.Canvas.rect(ToFixedPoint(y), ToFixedPoint(left), ToFixedRect(yOpen - y), ToFixedRect(dataWidth)); //空心柱
+ else this.Canvas.fillRect(ToFixedRect(y), ToFixedRect(left), ToFixedRect(yOpen - y), ToFixedRect(dataWidth));
+ }
+ }
+ else
+ {
+ if (Math.abs(yOpen - y) < 1)
+ {
+ this.Canvas.fillRect(ToFixedRect(left), ToFixedRect(y), ToFixedRect(dataWidth), 1); //高度小于1,统一使用高度1
+ }
+ else
+ {
+ if (this.DrawType == 3) this.Canvas.rect(ToFixedPoint(left), ToFixedPoint(y), ToFixedRect(dataWidth), ToFixedRect(yOpen - y)); //空心柱
+ else this.Canvas.fillRect(ToFixedRect(left), ToFixedRect(y), ToFixedRect(dataWidth), ToFixedRect(yOpen - y));
+ }
+ }
+
+ if (data.Open > data.Low)
+ {
+ if (isHScreen)
+ {
+ this.Canvas.moveTo(ToFixedPoint(this.DrawType == 3 ? Math.min(yClose, yOpen) : y), ToFixedPoint(x));
+ this.Canvas.lineTo(ToFixedPoint(yLow), ToFixedPoint(x));
+ }
+ else
+ {
+ this.Canvas.moveTo(ToFixedPoint(x), ToFixedPoint(this.DrawType == 3 ? Math.max(yClose, yOpen) : y));
+ this.Canvas.lineTo(ToFixedPoint(x), ToFixedPoint(yLow));
+ }
+ }
+ }
+ else
+ {
+ if (isHScreen)
+ {
+ this.Canvas.moveTo(yHigh, ToFixedPoint(x));
+ this.Canvas.lineTo(yLow, ToFixedPoint(x));
+ }
+ else
+ {
+ this.Canvas.moveTo(ToFixedPoint(x), yHigh);
+ this.Canvas.lineTo(ToFixedPoint(x), yLow);
+ }
+ }
+ }
+ else if (data.Open > data.Close) //阴线
+ {
+ if (dataWidth >= 4)
+ {
+ if (data.High > data.Close) //上影线
+ {
+ if (isHScreen)
+ {
+ this.Canvas.moveTo(ToFixedPoint(y), ToFixedPoint(x));
+ this.Canvas.lineTo(ToFixedPoint(yOpen), ToFixedPoint(x));
+ }
+ else
+ {
+ this.Canvas.moveTo(ToFixedPoint(x), ToFixedPoint(y));
+ this.Canvas.lineTo(ToFixedPoint(x), ToFixedPoint(yOpen));
+ }
+ y = yOpen;
+ }
+ else
+ {
+ y = yOpen
+ }
+
+ if (isHScreen)
+ {
+ if (Math.abs(yClose - y) < 1) this.Canvas.fillRect(ToFixedRect(y), ToFixedRect(left), 1, ToFixedRect(dataWidth)); //高度小于1,统一使用高度1
+ else this.Canvas.fillRect(ToFixedRect(y), ToFixedRect(left), ToFixedRect(yClose - y), ToFixedRect(dataWidth));
+ }
+ else
+ {
+ if (Math.abs(yClose - y) < 1) this.Canvas.fillRect(ToFixedRect(left), ToFixedRect(y), ToFixedRect(dataWidth), 1); //高度小于1,统一使用高度1
+ else this.Canvas.fillRect(ToFixedRect(left), ToFixedRect(y), ToFixedRect(dataWidth), ToFixedRect(yClose - y));
+ }
+
+ if (data.Open > data.Low) //下影线
+ {
+ if (isHScreen)
+ {
+ this.Canvas.moveTo(ToFixedPoint(y), ToFixedPoint(x));
+ this.Canvas.lineTo(ToFixedPoint(yLow), ToFixedPoint(x));
+ }
+ else
+ {
+ this.Canvas.moveTo(ToFixedPoint(x), ToFixedPoint(y));
+ this.Canvas.lineTo(ToFixedPoint(x), ToFixedPoint(yLow));
+ }
+ }
+ }
+ else
+ {
+ if (isHScreen)
+ {
+ this.Canvas.moveTo(yHigh, ToFixedPoint(x));
+ this.Canvas.lineTo(yLow, ToFixedPoint(x));
+ }
+ else
+ {
+ this.Canvas.moveTo(ToFixedPoint(x), yHigh);
+ this.Canvas.lineTo(ToFixedPoint(x), yLow);
+ }
+ }
+ }
+ else // 平线
+ {
+ if (dataWidth >= 4)
+ {
+ if (data.High > data.Close) //上影线
+ {
+ if (isHScreen)
+ {
+ this.Canvas.moveTo(y, ToFixedPoint(x));
+ this.Canvas.lineTo(yOpen, ToFixedPoint(x));
+ }
+ else
+ {
+ this.Canvas.moveTo(ToFixedPoint(x), y);
+ this.Canvas.lineTo(ToFixedPoint(x), yOpen);
+ }
+
+ y = yOpen;
+ }
+ else
+ {
+ y = yOpen;
+ }
+
+ if (isHScreen)
+ {
+ this.Canvas.moveTo(ToFixedPoint(y), ToFixedPoint(left));
+ this.Canvas.lineTo(ToFixedPoint(y), ToFixedPoint(right));
+ }
+ else
+ {
+ this.Canvas.moveTo(ToFixedPoint(left), ToFixedPoint(y));
+ this.Canvas.lineTo(ToFixedPoint(right), ToFixedPoint(y));
+ }
+
+ if (data.Open > data.Low) //下影线
+ {
+ if (isHScreen)
+ {
+ this.Canvas.moveTo(ToFixedPoint(y), ToFixedPoint(x));
+ this.Canvas.lineTo(ToFixedPoint(yLow), ToFixedPoint(x));
+ }
+ else
+ {
+ this.Canvas.moveTo(ToFixedPoint(x), ToFixedPoint(y));
+ this.Canvas.lineTo(ToFixedPoint(x), ToFixedPoint(yLow));
+ }
+ }
+ }
+ else
+ {
+ if (isHScreen)
+ {
+ this.Canvas.moveTo(yHigh, ToFixedPoint(x));
+ this.Canvas.lineTo(yLow, ToFixedPoint(x));
+ }
+ else
+ {
+ this.Canvas.moveTo(ToFixedPoint(x), yHigh);
+ this.Canvas.lineTo(ToFixedPoint(x), yLow);
+ }
+ }
+ }
+
+ }
+
+ if (isFristDraw == false) this.Canvas.stroke();
+ }
+
+ this.DrawAKLine = function (firstOpen) //美国线
+ {
+ var isHScreen = (this.ChartFrame.IsHScreen === true);
+ var dataWidth = this.ChartFrame.DataWidth;
+ var distanceWidth = this.ChartFrame.DistanceWidth;
+ var xOffset = this.ChartBorder.GetLeft() + distanceWidth / 2.0 + 2.0;
+ if (isHScreen) xOffset = this.ChartBorder.GetTop() + distanceWidth / 2.0 + 2.0;
+ var chartright = this.ChartBorder.GetRight();
+ if (isHScreen) chartright = this.ChartBorder.GetBottom();
+ var xPointCount = this.ChartFrame.XPointCount;
+
+ var firstOverlayOpen = null;
+ this.Canvas.strokeStyle = this.Color;
+ for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth))
+ {
+ var data = this.Data.Data[i];
+ if (data.Open == null || data.High == null || data.Low == null || data.Close == null) continue;
+
+ if (firstOverlayOpen == null) firstOverlayOpen = data.Open;
+ var left = xOffset;
+ var right = xOffset + dataWidth;
+ if (right > chartright) break;
+ var x = left + (right - left) / 2;
+ var yLow = this.ChartFrame.GetYFromData(data.Low / firstOverlayOpen * firstOpen);
+ var yHigh = this.ChartFrame.GetYFromData(data.High / firstOverlayOpen * firstOpen);
+ var yOpen = this.ChartFrame.GetYFromData(data.Open / firstOverlayOpen * firstOpen);
+ var yClose = this.ChartFrame.GetYFromData(data.Close / firstOverlayOpen * firstOpen);
+
+ this.Canvas.beginPath(); //最高-最低
+ if (isHScreen)
+ {
+ this.Canvas.moveTo(yHigh, ToFixedPoint(x));
+ this.Canvas.lineTo(yLow, ToFixedPoint(x));
+ }
+ else
+ {
+ this.Canvas.moveTo(ToFixedPoint(x), yHigh);
+ this.Canvas.lineTo(ToFixedPoint(x), yLow);
+ }
+
+ this.Canvas.stroke();
+
+ if (dataWidth >= 4)
+ {
+ this.Canvas.beginPath(); //开盘
+ if (isHScreen)
+ {
+ this.Canvas.moveTo(ToFixedPoint(yOpen), left);
+ this.Canvas.lineTo(ToFixedPoint(yOpen), x);
+ }
+ else
+ {
+ this.Canvas.moveTo(left, ToFixedPoint(yOpen));
+ this.Canvas.lineTo(x, ToFixedPoint(yOpen));
+ }
+ this.Canvas.stroke();
+
+ this.Canvas.beginPath(); //收盘
+ if (isHScreen)
+ {
+ this.Canvas.moveTo(ToFixedPoint(yClose), right);
+ this.Canvas.lineTo(ToFixedPoint(yClose), x);
+ }
+ else
+ {
+ this.Canvas.moveTo(right, ToFixedPoint(yClose));
+ this.Canvas.lineTo(x, ToFixedPoint(yClose));
+ }
+ this.Canvas.stroke();
+ }
+ }
+
+ }
+
+ this.DrawCloseLine = function (firstOpen) //收盘价线
+ {
+ var isHScreen = (this.ChartFrame.IsHScreen === true);
+ var dataWidth = this.ChartFrame.DataWidth;
+ var distanceWidth = this.ChartFrame.DistanceWidth;
+ var xOffset = this.ChartBorder.GetLeft() + distanceWidth / 2.0 + 2.0;
+ if (isHScreen) xOffset = this.ChartBorder.GetTop() + distanceWidth / 2.0 + 2.0;
+ var chartright = this.ChartBorder.GetRight();
+ if (isHScreen) chartright = this.ChartBorder.GetBottom();
+ var xPointCount = this.ChartFrame.XPointCount;
+
+ var firstOverlayOpen = null;
+ var bFirstPoint = true;
+ this.Canvas.strokeStyle = this.Color;
+ this.Canvas.beginPath();
+ for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth))
+ {
+ var data = this.Data.Data[i];
+ if (data.Open == null || data.High == null || data.Low == null || data.Close == null) continue;
+
+ if (firstOverlayOpen == null) firstOverlayOpen = data.Open;
+ var left = xOffset;
+ var right = xOffset + dataWidth;
+ if (right > chartright) break;
+ var x = left + (right - left) / 2;
+ var yClose = this.ChartFrame.GetYFromData(data.Close / firstOverlayOpen * firstOpen);
+
+ if (bFirstPoint)
+ {
+ if (isHScreen) this.Canvas.moveTo(yClose, x);
+ else this.Canvas.moveTo(x, yClose);
+ bFirstPoint = false;
+ }
+ else
+ {
+ if (isHScreen) this.Canvas.lineTo(yClose, x);
+ else this.Canvas.lineTo(x, yClose);
+ }
+ }
+
+ if (bFirstPoint == false) this.Canvas.stroke();
+ }
+
+ this.Draw = function ()
+ {
+ this.TooltipRect = [];
+ if (!this.MainData || !this.Data) return;
+
+ var xPointCount = this.ChartFrame.XPointCount;
+ var firstOpen = null; //主线数据第1个开盘价
+ for (var i = this.Data.DataOffset, j = 0; i < this.MainData.Data.length && j < xPointCount; ++i, ++j)
+ {
+ var data = this.MainData.Data[i];
+ if (data.Open == null || data.High == null || data.Low == null || data.Close == null) continue;
+ firstOpen = data.Open;
+ break;
+ }
+
+ if (firstOpen == null) return;
+
+ var drawTypeBackup = this.DrawType; //备份下线段类型
+ if (this.CustomDrawType != null) this.DrawType = this.CustomDrawType;
+
+ if (this.DrawType == 1) this.DrawCloseLine(firstOpen);
+ else if (this.DrawType == 2) this.DrawAKLine(firstOpen);
+ else this.DrawKBar(firstOpen);
+
+ this.DrawType = drawTypeBackup; //还原线段类型
+ }
+
+ this.GetMaxMin = function ()
+ {
+ var xPointCount = this.ChartFrame.XPointCount;
+ var range = {};
+ range.Max = null;
+ range.Min = null;
+
+ if (!this.MainData || !this.Data) return range;
+
+ var firstOpen = null; //主线数据第1个收盘价
+ for (var i = this.Data.DataOffset, j = 0; i < this.MainData.Data.length && j < xPointCount; ++i, ++j)
+ {
+ var data = this.MainData.Data[i];
+ if (data.Open == null || data.High == null || data.Low == null || data.Close == null) continue;
+ firstOpen = data.Close;
+ break;
+ }
+
+ if (firstOpen == null) return range;
+
+ var firstOverlayOpen = null;
+ var high, low;
+ for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j)
+ {
+ var data = this.Data.Data[i];
+ if (!data || data.Open == null || data.High == null || data.Low == null || data.Close == null) continue;
+ if (firstOverlayOpen == null) firstOverlayOpen = data.Open;
+
+ high = data.High / firstOverlayOpen * firstOpen;
+ low = data.Low / firstOverlayOpen * firstOpen;
+ if (range.Max == null) range.Max = high;
+ if (range.Min == null) range.Min = low;
+
+ if (range.Max < high) range.Max = high;
+ if (range.Min > low) range.Min = low;
+ }
+
+ return range;
+ }
+}
+
+// 多文本集合 支持横屏
+function ChartMultiText()
+{
+ this.newMethod = IChartPainting; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.ClassName ='ChartMultiText';
+ this.Texts = []; //[ {Index:, Value:, Text:, Color:, Font: , Baseline:, Line:{ Color:, Dash:[虚线点], KData:"H/L", Offset:[5,10], Width:线粗细 } } ]
+ this.Font = g_JSChartResource.DefaultTextFont;
+ this.Color = g_JSChartResource.DefaultTextColor;
+ this.IsHScreen = false; //是否横屏
+
+ this.Draw = function ()
+ {
+ if (!this.IsShow || this.ChartFrame.IsMinSize) return;
+ if (!this.Data || this.Data.length <= 0) return;
+ if (!this.Texts) return;
+
+ this.IsHScreen = (this.ChartFrame.IsHScreen === true);
+ var xPointCount = this.ChartFrame.XPointCount;
+ var offset = this.Data.DataOffset;
+ var left = this.ChartBorder.GetLeft();
+ var right = this.ChartBorder.GetRight();
+
+ if (this.IsHScreen)
+ {
+ left = this.ChartBorder.GetTop();
+ right = this.ChartBorder.GetBottom();
+ }
+
+ for (var i in this.Texts)
+ {
+ var item = this.Texts[i];
+ if (!item.Text) continue;
+ if (!IFrameSplitOperator.IsNumber(item.Index)) continue;
+
+ var index = item.Index - offset;
+ if (index >= 0 && index < xPointCount)
+ {
+ var x = this.ChartFrame.GetXFromIndex(index);
+ var y = this.ChartFrame.GetYFromData(item.Value);
+
+ if (item.Color) this.Canvas.fillStyle = item.Color;
+ else this.Canvas.fillStyle = this.Color;
+ if (item.Font) this.Canvas.font = item.Font;
+ else this.Canvas.font = this.Font;
+
+ var textWidth = this.Canvas.measureText(item.Text).width;
+ this.Canvas.textAlign = 'center';
+ if (x + textWidth / 2 >= right)
+ {
+ this.Canvas.textAlign = 'right';
+ x = right;
+ }
+ else if (x - textWidth / 2 < left)
+ {
+ this.Canvas.textAlign = 'left';
+ x = left;
+ }
+ if (item.Baseline == 1) this.Canvas.textBaseline = 'top';
+ else if (item.Baseline == 2) this.Canvas.textBaseline = 'bottom';
+ else this.Canvas.textBaseline = 'middle';
+ if (this.IsHScreen) //横屏旋转
+ {
+ this.Canvas.save();
+ this.Canvas.translate(y, x);
+ this.Canvas.rotate(90 * Math.PI / 180);
+ this.Canvas.fillText(item.Text, 0, 0);
+ this.Canvas.restore();
+ }
+ else
+ {
+ this.Canvas.fillText(item.Text, x, y);
+ }
+
+ if (item.Line)
+ {
+ var kItem=this.Data.Data[item.Index];
+ var price=item.Line.KData=="H"? kItem.High:kItem.Low;
+ var yPrice=this.ChartFrame.GetYFromData(price);
+ var yText=y;
+ if (Array.isArray(item.Line.Offset) && item.Line.Offset.length==2)
+ {
+ if (yText>yPrice) //文字在下方
+ {
+ yText-=item.Line.Offset[1];
+ yPrice+=item.Line.Offset[0]
+ }
+ else if (yText0) this.Canvas.lineWidth=item.Line.Width; //线宽
+ this.Canvas.strokeStyle = item.Line.Color;
+ this.Canvas.beginPath();
+ if (this.IsHScreen)
+ {
+ this.Canvas.moveTo(yText,ToFixedPoint(x));
+ this.Canvas.lineTo(yPrice,ToFixedPoint(x));
+ }
+ else
+ {
+ this.Canvas.moveTo(ToFixedPoint(x),yText);
+ this.Canvas.lineTo(ToFixedPoint(x),yPrice);
+ }
+ this.Canvas.stroke();
+ this.Canvas.restore();
+ }
+ }
+ }
+ }
+
+ this.GetMaxMin = function ()
+ {
+ var range = { Min: null, Max: null };
+ if (!this.Texts) return range;
+
+ var xPointCount = this.ChartFrame.XPointCount;
+ var start = this.Data.DataOffset;
+ var end = start + xPointCount;
+
+ for (var i in this.Texts)
+ {
+ var item = this.Texts[i];
+ if (item.Index >= start && item.Index < end)
+ {
+ if (range.Max == null) range.Max = item.Value;
+ else if (range.Max < item.Value) range.Max = item.Value;
+ if (range.Min == null) range.Min = item.Value;
+ else if (range.Min > item.Value) range.Min = item.Value;
+ }
+ }
+
+ return range;
+ }
+}
+
+// 多dom节点
+function ChartMultiHtmlDom()
+{
+ this.newMethod=IChartPainting; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.ClassName="ChartMultiHtmlDom";
+ this.Texts=[]; //[ {Index:, Value:, Text: ] Text=dom内容
+ this.IsHScreen=false; //是否横屏
+ this.DrawCallback; //function(op, obj) op:1=开始 2=结束 3=绘制单个数据
+ this.DrawItem=[];
+
+ this.Draw=function()
+ {
+ this.DrawItem=[];
+ if (this.DrawCallback) this.DrawCallback(1, {Self:this} );
+
+ this.DrawDom();
+
+ if (this.DrawCallback) this.DrawCallback(2, { Self:this, Draw:this.DrawItem } );
+ }
+
+ this.DrawDom=function()
+ {
+ if (!this.IsShow || this.ChartFrame.IsMinSize) return;
+ if (!this.Data || this.Data.length<=0) return;
+
+ this.IsHScreen=(this.ChartFrame.IsHScreen===true);
+ var xPointCount=this.ChartFrame.XPointCount;
+ var offset=this.Data.DataOffset;
+
+ for(var i in this.Texts)
+ {
+ var item=this.Texts[i];
+
+ if (!item.Text) continue;
+ if (!IFrameSplitOperator.IsNumber(item.Index)) continue;
+
+ var index=item.Index-offset;
+ var kItem=this.Data.Data[item.Index]; //K线数据
+ var obj={ KData:kItem, Item:item, IsShow:false, Self:this };
+ if (index>=0 && index=start && item.Indexitem.Value) range.Min=item.Value;
+ }
+ }
+
+ return range;
+ }
+}
+
+// 线段集合 支持横屏
+function ChartMultiLine()
+{
+ this.newMethod = IChartPainting; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.Lines = []; // [ {Point:[ {Index, Value }, ], Color: }, ]
+ this.IsHScreen = false;
+ this.LineWidth=1;
+ this.LineDash;
+
+ this.Draw = function ()
+ {
+ if (!this.IsShow || this.ChartFrame.IsMinSize) return;
+ if (!this.Data || this.Data.length <= 0) return;
+
+ this.IsHScreen = (this.ChartFrame.IsHScreen === true);
+ var xPointCount = this.ChartFrame.XPointCount;
+ var offset = this.Data.DataOffset;
+
+ var drawLines = [];
+ for (var i in this.Lines)
+ {
+ var line = this.Lines[i];
+ var drawPoints = { Point: [], Color: line.Color };
+ for (var j in line.Point)
+ {
+ var point = line.Point[j];
+ if (!IFrameSplitOperator.IsNumber(point.Index)) continue;
+
+ var index = point.Index - offset;
+ if (index >= 0 && index < xPointCount)
+ {
+ var x = this.ChartFrame.GetXFromIndex(index);
+ var y = this.ChartFrame.GetYFromData(point.Value);
+ drawPoints.Point.push({ X: x, Y: y });
+ }
+ }
+
+ if (drawPoints.Point.length >= 2) drawLines.push(drawPoints)
+ }
+
+ this.Canvas.save();
+ for (var i in drawLines)
+ {
+ if (this.LineDash) this.Canvas.setLineDash(this.LineDash);
+ if (IFrameSplitOperator.IsPlusNumber(this.LineWidth)) this.Canvas.lineWidth=this.LineWidth;
+ else this.Canvas.lineWidth=1;
+
+ var item = drawLines[i];
+ this.DrawLine(item);
+ }
+ this.Canvas.restore();
+ }
+
+ this.DrawLine = function (line)
+ {
+ this.Canvas.strokeStyle = line.Color;
+ for (var i in line.Point)
+ {
+ var item = line.Point[i];
+ if (i == 0)
+ {
+ this.Canvas.beginPath();
+ if (this.IsHScreen) this.Canvas.moveTo(item.Y, item.X);
+ else this.Canvas.moveTo(item.X, item.Y);
+ }
+ else
+ {
+ if (this.IsHScreen) this.Canvas.lineTo(item.Y, item.X);
+ else this.Canvas.lineTo(item.X, item.Y);
+ }
+ }
+ this.Canvas.stroke();
+ }
+
+ this.GetMaxMin = function ()
+ {
+ var range = { Min: null, Max: null };
+ var xPointCount = this.ChartFrame.XPointCount;
+ var start = this.Data.DataOffset;
+ var end = start + xPointCount;
+
+ for (var i in this.Lines)
+ {
+ var line = this.Lines[i];
+ for (var j in line.Point)
+ {
+ var point = line.Point[j];
+ if (point.Index >= start && point.Index < end)
+ {
+ if (range.Max == null) range.Max = point.Value;
+ else if (range.Max < point.Value) range.Max = point.Value;
+ if (range.Min == null) range.Min = point.Value;
+ else if (range.Min > point.Value) range.Min = point.Value;
+ }
+ }
+ }
+
+ return range;
+ }
+}
+
+// 柱子集合 支持横屏
+function ChartMultiBar()
+{
+ this.newMethod = IChartPainting; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.Bars = []; // [ {Point:[ {Index, Value, Value2 }, ], Color:, Width: , Type: 0 实心 1 空心 }, ]
+ this.IsHScreen = false;
+
+ this.Draw = function ()
+ {
+ if (!this.IsShow || this.ChartFrame.IsMinSize) return;
+ if (!this.Data || this.Data.length <= 0) return;
+
+ this.IsHScreen = (this.ChartFrame.IsHScreen === true);
+ var xPointCount = this.ChartFrame.XPointCount;
+ var offset = this.Data.DataOffset;
+ var dataWidth = this.ChartFrame.DataWidth;
+
+ var drawBars = [];
+ for (var i in this.Bars)
+ {
+ var item = this.Bars[i];
+ var drawPoints = { Point: [], Color: item.Color, Width: dataWidth, Type: 0 };
+ if (item.Type > 0) drawPoints.Type = item.Type;
+ if (item.Width > 0)
+ {
+ drawPoints.Width = item.Width;
+ if (drawPoints.Width > dataWidth) drawPoints.Width = dataWidth;
+ }
+ else
+ {
+ if (drawPoints.Width < 4) drawPoints.Width = 1;
+ }
+
+ for (var j in item.Point)
+ {
+ var point = item.Point[j];
+ if (!IFrameSplitOperator.IsNumber(point.Index)) continue;
+
+ var index = point.Index - offset;
+ if (index >= 0 && index < xPointCount)
+ {
+ var x = this.ChartFrame.GetXFromIndex(index);
+ var y = this.ChartFrame.GetYFromData(point.Value);
+ var y2 = this.ChartFrame.GetYFromData(point.Value2);
+ drawPoints.Point.push({ X: x, Y: y, Y2: y2 });
+ }
+ }
+
+ if (drawPoints.Point.length > 0) drawBars.push(drawPoints)
+ }
+
+ for (var i in drawBars)
+ {
+ var item = drawBars[i];
+ if (item.Width >= 4)
+ {
+ if (item.Type == 1) this.DrawHollowBar(item);
+ else this.DrawFillBar(item);
+ }
+ else
+ {
+ this.DrawLineBar(item);
+ }
+ }
+ }
+
+ this.DrawLineBar = function (bar)
+ {
+ this.Canvas.strokeStyle = bar.Color;
+ var backupLineWidth = this.Canvas.lineWidth;
+ this.Canvas.lineWidth = bar.Width;
+ for (var i in bar.Point)
+ {
+ var item = bar.Point[i];
+
+ this.Canvas.beginPath();
+ if (this.IsHScreen)
+ {
+ this.Canvas.moveTo(ToFixedPoint(item.Y), ToFixedPoint(item.X));
+ this.Canvas.lineTo(ToFixedPoint(item.Y2), ToFixedPoint(item.X));
+ }
+ else
+ {
+ this.Canvas.moveTo(ToFixedPoint(item.X), ToFixedPoint(item.Y));
+ this.Canvas.lineTo(ToFixedPoint(item.X), ToFixedPoint(item.Y2));
+ }
+
+ this.Canvas.stroke();
+ }
+
+ this.Canvas.lineWidth = backupLineWidth;
+ }
+
+ this.DrawFillBar = function (bar)
+ {
+ this.Canvas.fillStyle = bar.Color;
+ for (var i in bar.Point)
+ {
+ var item = bar.Point[i];
+ var x = item.X - (bar.Width / 2);
+ var y = Math.min(item.Y, item.Y2);
+ var barWidth = bar.Width;
+ var barHeight = Math.abs(item.Y - item.Y2);
+ if (this.IsHScreen)
+ this.Canvas.fillRect(ToFixedRect(y), ToFixedRect(x), ToFixedRect(barHeight), ToFixedRect(barWidth));
+ else
+ this.Canvas.fillRect(ToFixedRect(x), ToFixedRect(y), ToFixedRect(barWidth), ToFixedRect(barHeight));
+ }
+ }
+
+ this.DrawHollowBar = function (bar) //空心柱子
+ {
+ this.Canvas.strokeStyle = bar.Color;
+ var backupLineWidth = 1;
+ for (var i in bar.Point)
+ {
+ var item = bar.Point[i];
+ var x = item.X - (bar.Width / 2);
+ var y = Math.min(item.Y, item.Y2);
+ var barWidth = bar.Width;
+ var barHeight = Math.abs(item.Y - item.Y2);
+ this.Canvas.beginPath();
+ if (this.IsHScreen)
+ this.Canvas.rect(ToFixedPoint(y), ToFixedPoint(x), ToFixedRect(barHeight), ToFixedRect(barWidth));
+ else
+ this.Canvas.rect(ToFixedPoint(x), ToFixedPoint(y), ToFixedRect(barWidth), ToFixedRect(barHeight));
+
+ this.Canvas.stroke();
+ }
+
+ this.Canvas.lineWidth = backupLineWidth;
+ }
+
+ this.GetMaxMin = function ()
+ {
+ var range = { Min: null, Max: null };
+ var xPointCount = this.ChartFrame.XPointCount;
+ var start = this.Data.DataOffset;
+ var end = start + xPointCount;
+ for (var i in this.Bars)
+ {
+ var item = this.Bars[i];
+ for (var j in item.Point)
+ {
+ var point = item.Point[j];
+ if (point.Index >= start && point.Index < end)
+ {
+ var minValue = Math.min(point.Value, point.Value2);
+ var maxValue = Math.max(point.Value, point.Value2);
+ if (range.Max == null) range.Max = maxValue;
+ else if (range.Max < maxValue) range.Max = maxValue;
+ if (range.Min == null) range.Min = minValue;
+ else if (range.Min > minValue) range.Min = minValue;
+ }
+ }
+ }
+
+ return range;
+ }
+}
+
+//分钟信息地雷 支持横屏
+function ChartMinuteInfo()
+{
+ this.newMethod = IChartPainting; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.ClassName = "ChartMinuteInfo";
+ this.Data = new Map() //Map key=date-time, value=[{Date, Time, Title, Type, ID:}]
+ this.SourceData;
+ this.ChartMinutePrice;
+ this.YClose;
+
+ this.TextColor = g_JSChartResource.MinuteInfo.TextColor;
+ this.Font = g_JSChartResource.MinuteInfo.Font;
+ this.PointColor = g_JSChartResource.MinuteInfo.PointColor;
+ this.LineColor = g_JSChartResource.MinuteInfo.LineColor;
+ this.TextBGColor = g_JSChartResource.MinuteInfo.TextBGColor;
+ this.TextHeight = 18;
+
+ this.TextRectCache = [];
+ this.InfoDrawCache = [];
+ this.FrameBottom;
+ this.FrameTop;
+ this.FrameLeft;
+ this.FrameRight;
+ this.YOffset = 5;
+ this.IsHScreen = false;
+
+ this.SetOption = function (option)
+ {
+ if (option.TextColor) this.TextColor = option.TextColor;
+ if (option.TextBGColor) this.TextBGColor = option.TextBGColor;
+ if (option.Font) this.Font = option.Font;
+ if (option.PointColor) this.PointColor = option.PointColor;
+ if (option.LineColor) this.LineColor = option.LineColor;
+ if (option.TextHeight > 0) this.TextHeight = option.TextHeight;
+ }
+
+ this.Draw = function ()
+ {
+ if (!this.ChartMinutePrice) return;
+ if (!this.Data || this.Data.size <= 0) return;
+
+ this.TextRectCache = [];
+ this.InfoDrawCache = [];
+ this.IsHScreen = (this.ChartFrame.IsHScreen === true);
+
+ var xPointCount = this.ChartFrame.XPointCount;
+ var minuteCount = this.ChartFrame.MinuteCount;
+
+ this.FrameBottom = this.ChartBorder.GetBottom();
+ this.FrameTop = this.ChartBorder.GetTop();
+ this.FrameLeft = this.ChartBorder.GetLeft();
+ this.FrameRight = this.ChartBorder.GetRight();
+ if (this.IsHScreen)
+ {
+ this.FrameRight = this.ChartBorder.GetBottom();
+ this.FrameLeft = this.ChartBorder.GetTop();
+ this.FrameBottom = this.ChartBorder.GetLeft();
+ this.FrameTop = this.ChartBorder.GetRight();
+ }
+
+ this.YClose = this.ChartMinutePrice.YClose;
+
+ var data = this.ChartMinutePrice.Data;
+ var isBeforeData = false;
+ if (this.ChartMinutePrice.SourceData)
+ {
+ data = this.ChartMinutePrice.SourceData;
+ isBeforeData = true;
+ }
+
+ this.Canvas.font = this.Font;
+ for (var i = data.DataOffset, j = 0; i < data.Data.length && j < xPointCount; ++i, ++j)
+ {
+ var item = this.SourceData.Data[i];
+ if (isBeforeData && item.Before) continue;
+ if (!item) continue;
+
+ var dateTime = item.DateTime;
+ if (!this.Data.has(dateTime)) continue;
+ if (this.IsHScreen)
+ this.CalcuateInfoHScreenPosition(this.Data.get(dateTime), j, item);
+ else
+ this.CalcuateInfoPosition(this.Data.get(dateTime), j, item);
+ }
+
+ for (var i in this.InfoDrawCache)
+ {
+ var item = this.InfoDrawCache[i];
+ this.DrawInfoLines(item);
+ }
+
+ for (var i in this.InfoDrawCache)
+ {
+ var item = this.InfoDrawCache[i];
+ this.DrawInfoText(item);
+ }
+
+ this.TextRectCache = [];
+ this.InfoDrawCache = [];
+ }
+
+ this.CalcuateInfoPosition = function (infoItem, index, minuteItem)
+ {
+ if (!infoItem || !infoItem.Data || infoItem.Data.length <= 0) return;
+
+ var showItem = infoItem.Data[0];
+ var textWidth = this.Canvas.measureText(showItem.Title).width + 4;
+ var textHeight = this.TextHeight;
+
+ var x = this.ChartFrame.GetXFromIndex(index);
+ var y = this.ChartFrame.GetYFromData(minuteItem.Close);
+ x = ToFixedPoint(x);
+
+ var isDrawLeft = x < (this.FrameLeft + Math.abs(this.FrameLeft - this.FrameRight) / 2);
+
+ var ARRAY_OFFSET = [2, 4, 3, 2, 3, 3, 2];
+ var offset = textHeight + ARRAY_OFFSET[index % ARRAY_OFFSET.length];
+ var yData =
+ {
+ Y:
+ [
+ { Value: y + (textHeight + this.YOffset), Offset: offset },
+ { Value: y - (2 * textHeight + this.YOffset), Offset: -offset }
+ ]
+ };
+
+ if (minuteItem.Close < this.YClose)
+ yData.Y = yData.Y.reverse();
+
+ var rtBorder = { X: x, Y: null, Width: textWidth, Height: textHeight };
+ if (!isDrawLeft) rtBorder.X -= rtBorder.Width;
+
+ this.FixTextRect(rtBorder, yData);
+ var InfoDrawItem = { Border: rtBorder, Start: { X: x, Y: y }, IsLeft: isDrawLeft, Title: showItem.Title };
+
+ this.InfoDrawCache.push(InfoDrawItem);
+ this.TextRectCache.push(rtBorder);
+ }
+
+ this.CalcuateInfoHScreenPosition = function (infoItem, index, minuteItem)
+ {
+ if (!infoItem || !infoItem.Data || infoItem.Data.length <= 0) return;
+
+ var showItem = infoItem.Data[0];
+ var textHeight = this.Canvas.measureText(showItem.Title).width + 4;
+ var textWidth = this.TextHeight;
+
+ var y = this.ChartFrame.GetXFromIndex(index);
+ var x = this.ChartFrame.GetYFromData(minuteItem.Close);
+ y = ToFixedPoint(y);
+
+ var isDrawLeft = y < (this.FrameLeft + Math.abs(this.FrameLeft - this.FrameRight) / 2);
+
+ var ARRAY_OFFSET = [2, 4, 3, 2, 3, 3, 2];
+ var offset = textWidth + ARRAY_OFFSET[index % ARRAY_OFFSET.length];
+ var xData =
+ {
+ X:
+ [
+ { Value: x + (textWidth + this.YOffset), Offset: offset },
+ { Value: x - (2 * textWidth + this.YOffset), Offset: -offset }
+ ]
+ };
+
+ if (minuteItem.Close > this.YClose)
+ xData.X = xData.X.reverse();
+
+ var rtBorder = { X: null, Y: y, Width: textWidth, Height: textHeight };
+ if (!isDrawLeft) rtBorder.Y -= rtBorder.Height;
+
+ this.FixHScreenTextRect(rtBorder, xData);
+ var InfoDrawItem = { Border: rtBorder, Start: { X: x, Y: y }, IsLeft: isDrawLeft, Title: showItem.Title };
+
+ this.InfoDrawCache.push(InfoDrawItem);
+ this.TextRectCache.push(rtBorder);
+ }
+
+ this.DrawInfoLines = function (item)
+ {
+ var rtBorder = item.Border;
+ var isDrawLeft = item.IsLeft;
+ this.Canvas.strokeStyle = this.LineColor;
+ this.Canvas.beginPath();
+ this.Canvas.moveTo(item.Start.X, item.Start.Y);
+ if (isDrawLeft)
+ {
+ this.Canvas.lineTo(rtBorder.X, rtBorder.Y);
+ }
+ else
+ {
+ if (this.IsHScreen) this.Canvas.lineTo(rtBorder.X, rtBorder.Y + rtBorder.Height);
+ else this.Canvas.lineTo(rtBorder.X + rtBorder.Width, rtBorder.Y);
+ }
+ this.Canvas.stroke();
+
+ this.Canvas.fillStyle = this.PointColor;
+ this.Canvas.beginPath();
+ this.Canvas.arc(item.Start.X, item.Start.Y, 5, 0, 2 * Math.PI);
+ this.Canvas.closePath();
+ this.Canvas.fill();
+ }
+
+ this.DrawInfoText = function (item)
+ {
+ var rtBorder = item.Border;
+ var x = rtBorder.X, y = rtBorder.Y;
+ this.Canvas.fillStyle = this.TextBGColor;
+ this.Canvas.fillRect(x, y, rtBorder.Width, rtBorder.Height);
+
+ this.Canvas.strokeStyle = this.LineColor;
+ this.Canvas.beginPath();
+ this.Canvas.rect(x, y, rtBorder.Width, rtBorder.Height);
+ this.Canvas.stroke();
+
+ if (this.IsHScreen)
+ {
+ this.Canvas.save();
+ this.Canvas.translate(rtBorder.X, rtBorder.Y);
+ this.Canvas.rotate(90 * Math.PI / 180);
+ x = 0; y = 0;
+ }
+
+ this.Canvas.textAlign = 'left'
+ this.Canvas.textBaseline = 'middle';
+ this.Canvas.fillStyle = this.TextColor;
+ this.Canvas.font = this.Font;
+ if (this.IsHScreen) this.Canvas.fillText(item.Title, x + 2, y - rtBorder.Width / 2);
+ else this.Canvas.fillText(item.Title, x+2, y + rtBorder.Height / 2);
+
+ if (this.IsHScreen) this.Canvas.restore();
+ }
+
+ this.FixTextRect = function (rect, yData)
+ {
+ for (var k in yData.Y)
+ {
+ var yItem = yData.Y[k];
+ rect.Y = yItem.Value;
+
+ var y;
+ for (var j = 0; j < 10; ++j)
+ {
+ var isOverlap = false;
+ for (var i in this.TextRectCache)
+ {
+ var item = this.TextRectCache[i];
+ if (this.IsOverlap(item, rect))
+ {
+ isOverlap = true;
+ break;
+ }
+ }
+
+ if (isOverlap == false) return;
+
+ y = rect.Y;
+ y += yItem.Offset;
+ if (y + rect.Height > this.FrameBottom || y < this.FrameTop) break;
+
+ rect.Y = y;
+ }
+ }
+ }
+
+ this.FixHScreenTextRect = function (rect, xData)
+ {
+ for (var k in xData.X)
+ {
+ var xItem = xData.X[k];
+ rect.X = xItem.Value;
+
+ var x;
+ for (var j = 0; j < 10; ++j)
+ {
+ var isOverlap = false;
+ for (var i in this.TextRectCache)
+ {
+ var item = this.TextRectCache[i];
+ if (this.IsOverlap(item, rect))
+ {
+ isOverlap = true;
+ break;
+ }
+ }
+
+ if (isOverlap == false) return;
+
+ x = rect.X;
+ x += xItem.Offset;
+ if (x + rect.Width < this.FrameBottom || x > this.FrameTop) break;
+
+ rect.X = x;
+ }
+ }
+ }
+
+ this.IsOverlap = function (rc1, rc2)
+ {
+ if (rc1.X + rc1.Width > rc2.X && rc2.X + rc2.Width > rc1.X && rc1.Y + rc1.Height > rc2.Y && rc2.Y + rc2.Height > rc1.Y)
+ return true;
+ else
+ return false;
+ }
+
+ this.GetMaxMin = function ()
+ {
+ var range = { Min: null, Max: null };
+ return range;
+ }
+}
+
+//买卖盘
+function ChartBuySell()
+{
+ this.newMethod = ChartSingleText; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.ClassName = "ChartBuySell";
+ this.TextFont = g_JSChartResource.KLineTrain.Font; //"bold 14px arial"; //买卖信息字体
+ this.LastDataIcon = g_JSChartResource.KLineTrain.LastDataIcon; //{Color:'rgb(0,0,205)',Text:'↓'};
+ this.BuyIcon = g_JSChartResource.KLineTrain.BuyIcon; //{Color:'rgb(0,0,205)',Text:'B'};
+ this.SellIcon = g_JSChartResource.KLineTrain.SellIcon; //{Color:'rgb(0,0,205)',Text:'S'};
+ this.BuySellData = new Map(); //Key=数据索引index Value:Data:[ { Op: 买/卖 0=buy 1=sell, Date:, Time, Price: Vol:}, ]
+
+ this.AddTradeItem = function (tradeItem)
+ {
+ if (this.BuySellData.has(tradeItem.Key))
+ {
+ var Trade = this.BuySellData.get(tradeItem.Key);
+ Trade.Data.push(tradeItem);
+ }
+ else
+ {
+ this.BuySellData.set(tradeItem.Key, { Data: [tradeItem] });
+ }
+ }
+
+ this.ClearTradeData = function ()
+ {
+ this.BuySellData = new Map();
+ }
+
+ this.Draw = function ()
+ {
+ if (!this.Data || !this.Data.Data) return;
+
+ var isHScreen = (this.ChartFrame.IsHScreen === true);
+ var dataWidth = this.ChartFrame.DataWidth;
+ var distanceWidth = this.ChartFrame.DistanceWidth;
+ var chartright = this.ChartBorder.GetRight();
+ if (isHScreen === true) chartright = this.ChartBorder.GetBottom();
+ var xPointCount = this.ChartFrame.XPointCount;
+
+ var bottom = this.ChartBorder.GetBottomEx();
+ var top = this.ChartBorder.GetTopEx();
+ var height = this.ChartBorder.GetHeightEx();
+ if (isHScreen)
+ {
+ top = this.ChartBorder.GetRightEx();
+ bottom = this.ChartBorder.GetLeftEx();
+ height = this.ChartBorder.GetWidthEx();
+ }
+
+ this.Canvas.font = this.TextFont;
+ for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j)
+ {
+ var value = this.Data.Data[i];
+ if (value == null) continue;
+ if (x > chartright) break;
+
+ if (i == this.Data.Data.length - 1)
+ {
+ var x = this.ChartFrame.GetXFromIndex(j);
+ var yHigh = this.ChartFrame.GetYFromData(value.High);
+ if (this.LastDataIcon.Text)
+ {
+ this.Canvas.textAlign = 'center';
+ this.Canvas.textBaseline = 'bottom';
+ this.Canvas.fillStyle = this.LastDataIcon.Color;
+ this.Canvas.font = this.TextFont;
+ this.DrawText(this.LastDataIcon.Text, x, yHigh, isHScreen);
+ }
+ else
+ {
+ var obj =
+ {
+ X: x, Top: top, Bottom: bottom, Height: height,
+ DataWidth: dataWidth, Color: this.LastDataIcon.Color, IsHScreen: isHScreen,
+ };
+ this.DrawLastData(obj);
+ }
+ }
+
+ var key = i;
+ if (!this.BuySellData.has(key)) continue;
+
+ var trade = this.BuySellData.get(key);
+ var x = this.ChartFrame.GetXFromIndex(j);
+ var yHigh = this.ChartFrame.GetYFromData(value.High);
+ var yLow = this.ChartFrame.GetYFromData(value.Low);
+ var drawInfo = [false, false]; //0=buy 1=sell
+ for (var k in trade.Data)
+ {
+ if (drawInfo[0] == true && drawInfo[1] == true) break; //买卖图标只画一次
+
+ var bsItem = trade.Data[k];
+ if (bsItem.Op == 0 && drawInfo[0] == false) //买 标识在最低价上
+ {
+ this.Canvas.textAlign = 'center';
+ this.Canvas.textBaseline = 'top';
+ this.Canvas.fillStyle = this.BuyIcon.Color;
+ this.DrawText(this.BuyIcon.Text, x, yLow, isHScreen);
+ drawInfo[0] = true;
+ }
+ else if (bsItem.Op == 1 && drawInfo[1] == false) //卖 标识在最高价上
+ {
+ this.Canvas.textAlign = 'center';
+ this.Canvas.textBaseline = 'bottom';
+ this.Canvas.fillStyle = this.SellIcon.Color;
+ this.DrawText(this.SellIcon.Text, x, yHigh, isHScreen);
+ drawInfo[1] = true;
+ }
+ }
+ }
+ }
+
+ this.DrawLastData=function(obj)
+ {
+ this.Canvas.fillStyle = obj.Color;
+
+ var width = obj.DataWidth;
+ if (this.LastDataIcon.Width >= 2 && this.LastDataIcon.Width < obj.DataWidth)
+ width = this.LastDataIcon.Width;
+ var left = obj.X - width / 2;
+
+ if (obj.IsHScreen)
+ {
+ this.Canvas.fillRect(ToFixedRect(obj.Bottom), ToFixedRect(left), ToFixedRect(obj.Height), ToFixedRect(width));
+ }
+ else
+ {
+ var left = obj.X - width/2;
+ this.Canvas.fillRect(ToFixedRect(left), ToFixedRect(obj.Top), ToFixedRect(width), ToFixedRect(obj.Height));
+ }
+ }
+}
+
+//分钟成交量
+function ChartMinuteVolumBar()
+{
+ this.newMethod = IChartPainting; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.UpColor = g_JSChartResource.UpBarColor;
+ this.DownColor = g_JSChartResource.DownBarColor;
+ this.CustomColor=g_JSChartResource.Minute.VolBarColor;
+ this.YClose; //前收盘
+
+ this.Draw = function ()
+ {
+ var isHScreen = (this.ChartFrame.IsHScreen === true)
+ var chartright = this.ChartBorder.GetRight();
+ if (isHScreen) chartright = this.ChartBorder.GetBottom();
+ var xPointCount = this.ChartFrame.XPointCount;
+ var yBottom = this.ChartFrame.GetYFromData(0);
+ var yPrice = this.YClose; //上一分钟的价格
+
+ if (this.CustomColor) this.Canvas.strokeStyle=this.CustomColor;
+ for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j)
+ {
+ var item = this.Data.Data[i];
+ if (!item || !item.Vol) continue;
+
+ var y = this.ChartFrame.GetYFromData(item.Vol);
+ var x = this.ChartFrame.GetXFromIndex(i);
+ if (x > chartright) break;
+ //价格>=上一分钟价格 红色 否则绿色
+ if (!this.CustomColor) this.Canvas.strokeStyle = item.Close >= yPrice ? this.UpColor : this.DownColor;
+ this.Canvas.beginPath();
+ if (isHScreen)
+ {
+ this.Canvas.moveTo(y, ToFixedPoint(x));
+ this.Canvas.lineTo(yBottom, ToFixedPoint(x));
+ }
+ else
+ {
+ this.Canvas.moveTo(ToFixedPoint(x), y);
+ this.Canvas.lineTo(ToFixedPoint(x), yBottom);
+ }
+ this.Canvas.stroke();
+ yPrice = item.Close;
+ }
+ }
+
+ this.GetMaxMin = function ()
+ {
+ var xPointCount = this.ChartFrame.XPointCount;
+ var range = {};
+ range.Min = 0;
+ range.Max = null;
+ for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j)
+ {
+ var item = this.Data.Data[i];
+ if (!item || !item.Vol) continue;
+ if (range.Max == null) range.Max = item.Vol;
+ if (range.Max < item.Vol) range.Max = item.Vol;
+ }
+
+ return range;
+ }
+ }
+
+//MACD森林线 支持横屏
+function ChartMACD()
+{
+ this.newMethod = IChartPainting; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.ClassName ='ChartMACD';
+ this.UpColor = g_JSChartResource.UpBarColor;
+ this.DownColor = g_JSChartResource.DownBarColor;
+ this.LineWidth=1;
+
+ this.Draw = function ()
+ {
+ if (this.ChartFrame.IsMinSize) return;
+ if (this.NotSupportMessage)
+ {
+ this.DrawNotSupportmessage();
+ return;
+ }
+
+ if (this.ChartFrame.IsHScreen === true)
+ {
+ this.HScreenDraw();
+ return;
+ }
+
+ var isMinute=this.IsMinuteFrame();
+ var dataWidth = this.ChartFrame.DataWidth;
+ var distanceWidth = this.ChartFrame.DistanceWidth;
+ var xOffset=this.ChartBorder.GetLeft()+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin;
+ var chartright = this.ChartBorder.GetRight();
+ var xPointCount = this.ChartFrame.XPointCount;
+
+ var lineWidth=this.LineWidth;
+ if (this.LineWidth==50) lineWidth=dataWidth;
+ else if (lineWidth>dataWidth) lineWidth=dataWidth;
+
+ this.Canvas.save();
+ this.Canvas.lineWidth=lineWidth;
+
+ var bFirstPoint = true;
+ var drawCount = 0;
+ var yBottom = this.ChartFrame.GetYFromData(0);
+ for(var i=this.Data.DataOffset,j=0;ichartright) break;
+ var x=left+(right-left)/2;
+ }
+ var y = this.ChartFrame.GetYFromData(value);
+
+ if (x > chartright) break;
+
+ var xFix = parseInt(x.toString()) + 0.5; //毛边修正
+ this.Canvas.beginPath();
+ this.Canvas.moveTo(xFix, yBottom);
+ this.Canvas.lineTo(xFix, y);
+
+ if (value >= 0) this.Canvas.strokeStyle = this.UpColor;
+ else this.Canvas.strokeStyle = this.DownColor;
+ this.Canvas.stroke();
+ this.Canvas.closePath();
+ }
+
+ this.Canvas.restore();
+ }
+
+ this.HScreenDraw = function ()
+ {
+ var isMinute=this.IsMinuteFrame();
+ var dataWidth = this.ChartFrame.DataWidth;
+ var distanceWidth = this.ChartFrame.DistanceWidth;
+ var xOffset=this.ChartBorder.GetTop()+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin;
+ var chartright = this.ChartBorder.GetBottom();
+ var xPointCount = this.ChartFrame.XPointCount;
+ var yBottom = this.ChartFrame.GetYFromData(0);
+
+ var lineWidth=this.LineWidth;
+ if (this.LineWidth==50) lineWidth=dataWidth;
+ else if (lineWidth>dataWidth) lineWidth=dataWidth;
+
+ this.Canvas.save();
+ this.Canvas.lineWidth=lineWidth;
+ for(var i=this.Data.DataOffset,j=0;ichartright) break;
+ var x=left+(right-left)/2;
+ }
+ var y = this.ChartFrame.GetYFromData(value);
+
+ if (x > chartright) break;
+
+ this.Canvas.beginPath();
+ this.Canvas.moveTo(yBottom, ToFixedPoint(x));
+ this.Canvas.lineTo(y, ToFixedPoint(x));
+
+ if (value >= 0) this.Canvas.strokeStyle = this.UpColor;
+ else this.Canvas.strokeStyle = this.DownColor;
+ this.Canvas.stroke();
+ this.Canvas.closePath();
+ }
+
+ this.Canvas.restore();
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// 等待提示
+function ChartSplashPaint()
+{
+ this.newMethod = IChartPainting; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.Font = g_JSChartResource.DefaultTextFont; //字体
+ this.TextColor = g_JSChartResource.DefaultTextColor; //文本颜色
+ this.IsEnableSplash = false;
+ this.SplashTitle = '数据加载中.....';
+ this.HQChart;
+
+ this.EnableSplash=function(bEnable)
+ {
+ this.IsEnableSplash=bEnable;
+ if (this.HQChart)
+ {
+ var event=this.HQChart.GetEnableSplashEvent();
+ if (event)
+ {
+ var data={ Enable:bEnable };
+ event.Callback(event,data,this);
+ }
+ }
+ }
+
+ this.SetTitle=function(title)
+ {
+ this.SplashTitle=title;
+ }
+
+ this.Draw = function ()
+ {
+ if (!this.IsEnableSplash) return;
+
+ if (this.Frame.IsHScreen === true)
+ {
+ this.HScreenDraw();
+ return;
+ }
+
+ var xCenter = (this.Frame.ChartBorder.GetLeft() + this.Frame.ChartBorder.GetRight()) / 2;
+ var yCenter = (this.Frame.ChartBorder.GetTop() + this.Frame.ChartBorder.GetBottom()) / 2;
+ this.Canvas.textAlign = 'center';
+ this.Canvas.textBaseline = 'middle';
+ this.Canvas.fillStyle = this.TextColor;
+ this.Canvas.font = this.Font;
+ this.Canvas.fillText(this.SplashTitle, xCenter, yCenter);
+ }
+
+ this.HScreenDraw = function () //横屏
+ {
+ var xCenter = (this.Frame.ChartBorder.GetLeft() + this.Frame.ChartBorder.GetRight()) / 2;
+ var yCenter = (this.Frame.ChartBorder.GetTop() + this.Frame.ChartBorder.GetBottom()) / 2;
+
+ this.Canvas.save();
+ this.Canvas.translate(xCenter, yCenter);
+ this.Canvas.rotate(90 * Math.PI / 180); //数据和框子旋转180度
+
+ this.Canvas.textAlign = 'center';
+ this.Canvas.textBaseline = 'middle';
+ this.Canvas.fillStyle = this.TextColor;
+ this.Canvas.font = this.Font;
+ this.Canvas.fillText(this.SplashTitle, 0, 0);
+
+ this.Canvas.restore();
+ }
+}
+
+//填充背景 支持横屏
+function ChartBackground()
+{
+ this.newMethod=IChartPainting; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.ClassName="ChartBackground";
+ this.Color=null;
+ this.ColorAngle=0; //0 竖向 1 横向
+ this.IsDrawFirst = true; //面积图在K线前面画,否则回挡住K线的
+ this.IsHScreen=false;
+
+ this.Draw=function()
+ {
+ if (!this.IsShow || this.ChartFrame.IsMinSize) return;
+ if (!this.Color) return;
+ if (this.Color.length<=0) return;
+ this.IsHScreen=(this.ChartFrame.IsHScreen===true);
+
+ if (this.Color.length==2)
+ {
+ if (this.IsHScreen)
+ {
+ if (this.ColorAngle==0)
+ {
+ var ptStart={ X:this.ChartBorder.GetRight(), Y:this.ChartBorder.GetTopEx() };
+ var ptEnd={ X:this.ChartBorder.GetLeft(), Y:this.ChartBorder.GetTopEx() };
+ }
+ else
+ {
+ var ptStart={ X:this.ChartBorder.GetLeft(), Y:this.ChartBorder.GetTopEx() };
+ var ptEnd={ X:this.ChartBorder.GetLeft(), Y:this.ChartBorder.GetBottomEx() };
+ }
+ }
+ else
+ {
+ if (this.ColorAngle==0)
+ {
+ var ptStart={ X:this.ChartBorder.GetLeft(), Y:this.ChartBorder.GetTopEx() };
+ var ptEnd={ X:this.ChartBorder.GetLeft(), Y:this.ChartBorder.GetBottomEx() };
+ }
+ else
+ {
+ var ptStart={ X:this.ChartBorder.GetLeft(), Y:this.ChartBorder.GetTopEx() };
+ var ptEnd={ X:this.ChartBorder.GetRight(), Y:this.ChartBorder.GetTopEx() };
+ }
+ }
+
+ let gradient = this.Canvas.createLinearGradient(ptStart.X,ptStart.Y, ptEnd.X,ptEnd.Y);
+ gradient.addColorStop(0, this.Color[0]);
+ gradient.addColorStop(1, this.Color[1]);
+ this.Canvas.fillStyle=gradient;
+ }
+ else if (this.Color.length==1)
+ {
+ this.Canvas.fillStyle=this.Color[0];
+ }
+ else
+ {
+ return;
+ }
+
+ if (this.Name=="DRAWGBK2" || this.Name=="KLINE_BG")
+ {
+ this.DrawRegion();
+ return;
+ }
+
+ if (this.IsHScreen)
+ {
+ var left=this.ChartBorder.GetLeftEx();
+ var top=this.ChartBorder.GetTop();
+ var width=this.ChartBorder.GetWidthEx();
+ var height=this.ChartBorder.GetHeight();
+ }
+ else
+ {
+ var left=this.ChartBorder.GetLeft();
+ var top=this.ChartBorder.GetTopEx();
+ var width=this.ChartBorder.GetWidth();
+ var height=this.ChartBorder.GetHeightEx();
+ }
+ this.Canvas.fillRect(left, top,width, height);
+ }
+
+ this.DrawRegion=function()
+ {
+ var xPointCount=this.ChartFrame.XPointCount;
+ var xOffset=this.ChartBorder.GetLeft()+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin;
+ var dataWidth=this.ChartFrame.DataWidth;
+ var distanceWidth=this.ChartFrame.DistanceWidth;
+ var top=this.ChartBorder.GetTopEx();
+ var bottom=this.ChartBorder.GetBottomEx();
+ if (this.IsHScreen)
+ {
+ top=this.ChartBorder.GetRightEx();
+ bottom=this.ChartBorder.GetLeftEx();
+ }
+
+ var aryPoint=[]; //点坐标
+ for(var i=this.Data.DataOffset,j=0;i0)
+ {
+ for(var j=aryLine2.length-1; j>=0; --j)
+ {
+ var item2=aryLine2[j];
+ if (this.IsHScreen)
+ {
+ this.Canvas.lineTo(item2.Line2.X, item2.Line2.Y+halfWidth);
+ this.Canvas.lineTo(item2.Line2.X, item2.Line2.Y-halfWidth);
+ }
+ else
+ {
+ this.Canvas.lineTo(item2.Line2.X+halfWidth, item2.Line2.Y);
+ this.Canvas.lineTo(item2.Line2.X-halfWidth, item2.Line2.Y);
+ }
+ }
+ this.Canvas.closePath();
+ this.Canvas.fill();
+ }
+
+ firstPoint=true;
+ pointCount=0;
+ aryLine2=[];
+ color=null;
+ }
+
+ if (!item) continue;
+
+ if (firstPoint)
+ {
+ this.Canvas.beginPath();
+ if (this.IsHScreen)
+ {
+ this.Canvas.moveTo(item.Line.X, item.Line.Y-halfWidth);
+ this.Canvas.lineTo(item.Line.X, item.Line.Y+halfWidth);
+ }
+ else
+ {
+ this.Canvas.moveTo(item.Line.X-halfWidth, item.Line.Y);
+ this.Canvas.lineTo(item.Line.X+halfWidth, item.Line.Y);
+ }
+ firstPoint=false;
+ color=item.Color;
+ }
+ else
+ {
+ if (this.IsHScreen)
+ {
+ this.Canvas.lineTo(item.Line.X, item.Line.Y-halfWidth);
+ this.Canvas.lineTo(item.Line.X, item.Line.Y+halfWidth);
+ }
+ else
+ {
+ this.Canvas.lineTo(item.Line.X-halfWidth, item.Line.Y);
+ this.Canvas.lineTo(item.Line.X+halfWidth, item.Line.Y);
+ }
+ }
+
+ aryLine2.push(item);
+ ++pointCount;
+ }
+
+ if (pointCount>0)
+ {
+ for(var j=aryLine2.length-1; j>=0; --j)
+ {
+ var item2=aryLine2[j];
+ if (this.IsHScreen)
+ {
+ this.Canvas.lineTo(item2.Line2.X, item2.Line2.Y+halfWidth);
+ this.Canvas.lineTo(item2.Line2.X, item2.Line2.Y-halfWidth);
+ }
+ else
+ {
+ this.Canvas.lineTo(item2.Line2.X+halfWidth, item2.Line2.Y);
+ this.Canvas.lineTo(item2.Line2.X-halfWidth, item2.Line2.Y);
+ }
+
+ }
+ this.Canvas.closePath();
+ this.Canvas.fill();
+ }
+ }
+
+ this.GetMaxMin=function()
+ {
+ return { Min:null, Max:null };
+ }
+}
+
+//锁 支持横屏
+function ChartLock()
+{
+ this.newMethod = IChartPainting; //派生
+ this.newMethod();
+ delete this.newMethod;
+ this.WidthDiv = 0.2; // 框子宽度占比
+ this.LockCount = 10; // 锁最新的几个数据
+ this.BGColor = g_JSChartResource.LockBGColor;
+ this.TextColor = g_JSChartResource.LockTextColor;
+ this.Font = g_JSChartResource.DefaultTextFont;
+ this.Title = '🔒开通权限';
+ this.LockRect = null; //上锁区域
+ this.LockID; //锁ID
+ this.Callback; //回调
+ this.IndexName; //指标名字
+
+ this.Draw = function ()
+ {
+ this.LockRect = null;
+ if (this.ChartFrame.IsMinSize) return;
+ if (this.NotSupportMessage)
+ {
+ this.DrawNotSupportmessage();
+ return;
+ }
+
+ if (this.ChartFrame.IsHScreen === true)
+ {
+ this.HScreenDraw();
+ return;
+ }
+
+ var xOffset = this.ChartBorder.GetRight();
+ var lOffsetWidth = 0;
+ if (this.ChartFrame.Data != null)
+ {
+ var dataWidth = this.ChartFrame.DataWidth;
+ var distanceWidth = this.ChartFrame.DistanceWidth;
+ xOffset = this.ChartBorder.GetLeft() + distanceWidth / 2.0 + 2.0;
+ var chartright = this.ChartBorder.GetRight();
+ var xPointCount = this.ChartFrame.XPointCount;
+ for (var i = this.ChartFrame.Data.DataOffset, j = 0; i < this.ChartFrame.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth))
+ {
+ var data = this.ChartFrame.Data.Data[i];
+ if (data.Open == null || data.High == null || data.Low == null || data.Close == null) continue;
+
+ var left = xOffset;
+ var right = xOffset + dataWidth;
+ if (right > chartright) break;
+ }
+ lOffsetWidth = (dataWidth + distanceWidth) * this.LockCount;
+ }
+ if (lOffsetWidth == 0)
+ {
+ lOffsetWidth = (xOffset - this.ChartBorder.GetLeft()) * this.WidthDiv;
+ }
+ var lLeft = xOffset - lOffsetWidth;
+ if (lLeft < this.ChartBorder.GetLeft())
+ lLeft = this.ChartBorder.GetLeft();
+ var lHeight = this.ChartBorder.GetBottom() - this.ChartBorder.GetTop();
+ var lWidth = this.ChartBorder.GetRight() - lLeft;
+ this.Canvas.fillStyle = this.BGColor;
+ this.Canvas.fillRect(lLeft, this.ChartBorder.GetTop(), lWidth, lHeight);
+ var xCenter = lLeft + lWidth / 2;
+ var yCenter = this.ChartBorder.GetTop() + lHeight / 2;
+ this.Canvas.textAlign = 'center';
+ this.Canvas.textBaseline = 'middle';
+ this.Canvas.fillStyle = this.TextColor;
+ this.Canvas.font = this.Font;
+ this.Canvas.fillText(this.Title, xCenter, yCenter);
+
+ this.LockRect = { Left: lLeft, Top: this.ChartBorder.GetTop(), Width: lWidth, Heigh: lHeight }; //保存上锁区域
+ }
+
+ this.HScreenDraw = function ()
+ {
+ var xOffset = this.ChartBorder.GetBottom();
+
+ var lOffsetWidth = 0;
+
+ if (this.ChartFrame.Data != null)
+ {
+ var dataWidth = this.ChartFrame.DataWidth;
+ var distanceWidth = this.ChartFrame.DistanceWidth;
+ xOffset = this.ChartBorder.GetTop() + distanceWidth / 2.0 + 2.0;
+ var chartright = this.ChartBorder.GetBottom();
+ var xPointCount = this.ChartFrame.XPointCount;
+ //求最后1个数据的位置
+ for (var i = this.ChartFrame.Data.DataOffset, j = 0; i < this.ChartFrame.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth))
+ {
+ var data = this.ChartFrame.Data.Data[i];
+ if (data.Open == null || data.High == null || data.Low == null || data.Close == null) continue;
+
+ var left = xOffset;
+ var right = xOffset + dataWidth;
+ if (right > chartright) break;
+ }
+ lOffsetWidth = (dataWidth + distanceWidth) * this.LockCount;
+ }
+ if (lOffsetWidth == 0)
+ {
+ lOffsetWidth = (xOffset - this.ChartBorder.GetTop()) * this.WidthDiv;
+ }
+
+ var lLeft = xOffset - lOffsetWidth;
+ if (lLeft < this.ChartBorder.GetTop()) lLeft = this.ChartBorder.GetTop();
+ var lHeight = this.ChartBorder.GetRight() - this.ChartBorder.GetLeft();
+ var lWidth = this.ChartBorder.GetBottom() - lLeft;
+ this.Canvas.fillStyle = this.BGColor;
+ this.Canvas.fillRect(this.ChartBorder.GetLeft(), lLeft, lHeight, lWidth);
+
+ var xCenter = this.ChartBorder.GetLeft() + lHeight / 2;
+ var yCenter = lLeft + lWidth / 2;
+ this.Canvas.save();
+ this.Canvas.translate(xCenter, yCenter);
+ this.Canvas.rotate(90 * Math.PI / 180);
+ this.Canvas.textAlign = 'center';
+ this.Canvas.textBaseline = 'middle';
+ this.Canvas.fillStyle = this.TextColor;
+ this.Canvas.font = this.Font;
+ this.Canvas.fillText(this.Title, 0, 0);
+ this.Canvas.restore();
+
+ this.LockRect = { Left: this.ChartBorder.GetLeft(), Top: lLeft, Width: lHeight, Heigh: lWidth }; //保存上锁区域
+ }
+
+ //x,y是否在上锁区域
+ this.GetTooltipData = function (x, y, tooltip)
+ {
+ if (this.LockRect == null) return false;
+
+ if (this.IsPointInRect(x, y, this.LockRect.Left, this.LockRect.Top, this.LockRect.Width, this.LockRect.Heigh))
+ {
+ tooltip.Data = { ID: this.LockID, Callback: this.Callback, IndexName: this.IndexName };
+ tooltip.ChartPaint = this;
+ return true;
+ }
+
+ return false;
+ }
+
+ this.IsPointInRect = function (x, y, left, top, width, heigh)
+ {
+ if (x > left && x < left + width && y > top && y < top + heigh) return true;
+ return false;
+ }
+}
+
+//通达信语法 VOLSTICK 支持横屏
+function ChartVolStick()
+{
+ this.newMethod = IChartPainting; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.UpColor = g_JSChartResource.UpBarColor;
+ this.DownColor = g_JSChartResource.DownBarColor;
+ this.HistoryData; //历史数据
+ this.KLineDrawType = 0;
+ this.ClassName = 'ChartVolStick';
+ this.MinBarWidth=g_JSChartResource.MinKLineBarWidth; //最小的柱子宽度
+
+ this.Draw = function ()
+ {
+ if (this.ChartFrame.IsMinSize) return;
+ if (this.ChartFrame.IsHScreen === true)
+ {
+ this.HScreenDraw();
+ return;
+ }
+
+ var dataWidth = this.ChartFrame.DataWidth;
+ var distanceWidth = this.ChartFrame.DistanceWidth;
+ var xOffset = this.ChartBorder.GetLeft() + distanceWidth / 2.0 + 2.0;
+ var chartright = this.ChartBorder.GetRight();
+ var xPointCount = this.ChartFrame.XPointCount;
+ var yBottom = this.ChartFrame.GetYFromData(0);
+ var isMinute=this.IsMinuteFrame();
+
+ if (dataWidth >= this.MinBarWidth)
+ { //只有K线, 分时图dataWidth=1
+ yBottom = ToFixedRect(yBottom);
+ for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth))
+ {
+ var value = this.Data.Data[i];
+ var kItem = this.HistoryData.Data[i];
+ if (value == null || kItem == null) continue;
+
+ var left = xOffset;
+ var right = xOffset + dataWidth;
+ if (right > chartright) break;
+
+ var y = this.ChartFrame.GetYFromData(value);
+ var bUp = false;
+ if (kItem.Close >= kItem.Open)
+ {
+ this.Canvas.fillStyle = this.UpColor;
+ bUp = true;
+ }
+ else
+ {
+ this.Canvas.fillStyle = this.DownColor;
+ }
+
+ //高度调整为整数
+ var height = ToFixedRect(Math.abs(yBottom - y)>=1 ? yBottom - y : 1);
+ y = yBottom - height;
+ if (bUp && (this.KLineDrawType == 1 || this.KLineDrawType == 2 || this.KLineDrawType == 3)) //空心柱子
+ {
+ this.Canvas.strokeStyle = this.UpColor;
+ this.Canvas.beginPath();
+ this.Canvas.rect(ToFixedPoint(left), ToFixedPoint(y), ToFixedRect(dataWidth), height);
+ this.Canvas.stroke();
+ }
+ else
+ {
+ this.Canvas.fillRect(ToFixedRect(left), y, ToFixedRect(dataWidth), height);
+ }
+ }
+ }
+ else //太细了直接话线
+ {
+ for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth))
+ {
+ var value = this.Data.Data[i];
+ var kItem = this.HistoryData.Data[i];
+ if (value == null || kItem == null) continue;
+
+ var y = this.ChartFrame.GetYFromData(value);
+
+ if (isMinute)
+ {
+ var x=this.ChartFrame.GetXFromIndex(j);
+ }
+ else
+ {
+ var left=xOffset;
+ var right=xOffset+dataWidth;
+ var x=left+(right-left)/2;
+ }
+
+ if (x > chartright) break;
+
+ if (kItem.Close > kItem.Open)
+ this.Canvas.strokeStyle = this.UpColor;
+ else
+ this.Canvas.strokeStyle = this.DownColor;
+
+ var x = this.ChartFrame.GetXFromIndex(j);
+ this.Canvas.beginPath();
+ this.Canvas.moveTo(ToFixedPoint(x), y);
+ this.Canvas.lineTo(ToFixedPoint(x), yBottom);
+ this.Canvas.stroke();
+ }
+ }
+ }
+
+ this.HScreenDraw = function () //横屏画法
+ {
+ var dataWidth = this.ChartFrame.DataWidth;
+ var distanceWidth = this.ChartFrame.DistanceWidth;
+ var xOffset = this.ChartBorder.GetTop() + distanceWidth / 2.0 + 2.0;
+ var chartBottom = this.ChartBorder.GetBottom();
+ var xPointCount = this.ChartFrame.XPointCount;
+
+ var yBottom = this.ChartFrame.GetYFromData(0);
+
+ if (dataWidth >= this.MinBarWidth)
+ {
+ yBottom = ToFixedRect(yBottom);
+ for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth))
+ {
+ var value = this.Data.Data[i];
+ var kItem = this.HistoryData.Data[i];
+ if (value == null || kItem == null) continue;
+
+ var left = xOffset;
+ var right = xOffset + dataWidth;
+ if (right > chartBottom) break;
+
+ var y = this.ChartFrame.GetYFromData(value);
+ var bUp = false;
+
+ if (kItem.Close >= kItem.Open)
+ {
+ bUp = true;
+ this.Canvas.fillStyle = this.UpColor;
+ }
+ else
+ {
+ this.Canvas.fillStyle = this.DownColor;
+ }
+
+ //高度调整为整数
+ var height = ToFixedRect(y - yBottom);
+ if (bUp && (this.KLineDrawType == 1 || this.KLineDrawType == 2 || this.KLineDrawType == 3)) //空心柱子
+ {
+ this.Canvas.strokeStyle = this.UpColor;
+ this.Canvas.beginPath();
+ this.Canvas.rect(ToFixedPoint(yBottom), ToFixedPoint(left), height, ToFixedRect(dataWidth));
+ this.Canvas.stroke();
+ }
+ else
+ {
+ this.Canvas.fillRect(yBottom, ToFixedRect(left), height, ToFixedRect(dataWidth));
+ }
+ }
+ }
+ else //太细了直接话线
+ {
+ for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth))
+ {
+ var value = this.Data.Data[i];
+ var kItem = this.HistoryData.Data[i];
+ if (value == null || kItem == null) continue;
+
+ var y = this.ChartFrame.GetYFromData(value);
+ var x = this.ChartFrame.GetXFromIndex(j);
+ if (x > chartBottom) break;
+
+ if (kItem.Close > kItem.Open)
+ this.Canvas.strokeStyle = this.UpColor;
+ else
+ this.Canvas.strokeStyle = this.DownColor;
+
+ var x = this.ChartFrame.GetXFromIndex(j);
+ this.Canvas.beginPath();
+ this.Canvas.moveTo(y, ToFixedPoint(x));
+ this.Canvas.lineTo(yBottom, ToFixedPoint(x));
+ this.Canvas.stroke();
+ }
+ }
+ }
+
+ this.GetMaxMin = function ()
+ {
+ var xPointCount = this.ChartFrame.XPointCount;
+ var range = {};
+ range.Min = 0;
+ range.Max = null;
+ for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j)
+ {
+ var value = this.Data.Data[i];
+ if (range.Max == null) range.Max = value;
+
+ if (range.Max < value) range.Max = value;
+ }
+
+ return range;
+ }
+}
+
+function ChartText()
+{
+ this.newMethod = IChartPainting; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.TextFont = "14px 微软雅黑";
+
+ this.Draw = function ()
+ {
+ if (this.ChartFrame.IsMinSize) return;
+ if (this.NotSupportMessage)
+ {
+ this.DrawNotSupportmessage();
+ return;
+ }
+
+ if (!this.Data || !this.Data.Data) return;
+
+ var dataWidth = this.ChartFrame.DataWidth;
+ var distanceWidth = this.ChartFrame.DistanceWidth;
+ var chartright = this.ChartBorder.GetRight();
+ var xPointCount = this.ChartFrame.XPointCount;
+
+ for (var i in this.Data.Data)
+ {
+ var value = this.Data.Data[i];
+ if (value == null) continue;
+
+ var price = value.Value;
+ var position = value.Position;
+
+ if (position == 'Left') {
+ var x = this.ChartFrame.GetXFromIndex(0);
+ var y = this.ChartFrame.GetYFromData(price);
+
+ if (x > chartright) continue;
+
+ this.Canvas.textAlign = 'left';
+ this.Canvas.textBaseline = 'middle';
+ this.Canvas.fillStyle = value.Color;
+ this.Canvas.font = this.TextFont;
+ this.Canvas.fillText(value.Message, x, y);
+ }
+ }
+ }
+
+ this.GetMaxMin = function ()
+ {
+ var xPointCount = this.ChartFrame.XPointCount;
+ var range = {};
+ range.Min = null;
+ range.Max = null;
+
+ if (!this.Data || !this.Data.Data) return range;
+
+ for (var i in this.Data.Data)
+ {
+ var data = this.Data.Data[i];
+ if (data == null || isNaN(data.Value)) continue;
+
+ var value = data.Value;
+
+ if (range.Max == null) range.Max = value;
+ if (range.Min == null) range.Min = value;
+
+ if (range.Max < value) range.Max = value;
+ if (range.Min > value) range.Min = value;
+ }
+
+ return range;
+ }
+}
+
+/* 水平面积 只有1个数据
+ Data 数据结构
+ Value, Value2 区间最大最小值
+ Color=面积的颜色
+ Title=标题 TitleColor=标题颜色
+ 支持横屏
+*/
+function ChartStraightArea()
+{
+ this.newMethod = IChartPainting; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.Color = "rgb(255,193,37)"; //线段颜色
+ this.Font = '11px 微软雅黑';
+
+ this.Draw = function ()
+ {
+ if (this.ChartFrame.IsMinSize) return;
+ if (this.NotSupportMessage)
+ {
+ this.DrawNotSupportmessage();
+ return;
+ }
+
+ if (!this.Data || !this.Data.Data) return;
+
+ if (this.ChartFrame.IsHScreen === true)
+ {
+ this.HScreenDraw();
+ return;
+ }
+
+ var dataWidth = this.ChartFrame.DataWidth;
+ var distanceWidth = this.ChartFrame.DistanceWidth;
+ var chartright = this.ChartBorder.GetRight();
+ var bottom = this.ChartBorder.GetBottom();
+ var left = this.ChartBorder.GetLeft();
+ var xPointCount = this.ChartFrame.XPointCount;
+
+ var xRight = this.ChartFrame.GetXFromIndex(xPointCount - 1);
+
+ //画背景
+ for (let i in this.Data.Data)
+ {
+ let item = this.Data.Data[i];
+ if (item == null || isNaN(item.Value) || isNaN(item.Value2)) continue;
+ if (item.Color == null) continue;
+
+ let valueMax = Math.max(item.Value, item.Value2);
+ let valueMin = Math.min(item.Value, item.Value2);
+
+ let yTop = this.ChartFrame.GetYFromData(valueMax);
+ let yBottom = this.ChartFrame.GetYFromData(valueMin);
+
+ this.Canvas.fillStyle = item.Color;
+ this.Canvas.fillRect(ToFixedRect(left), ToFixedRect(yTop), ToFixedRect(xRight - left), ToFixedRect(yBottom - yTop));
+ }
+
+ for (let i in this.Data.Data)
+ {
+ let item = this.Data.Data[i];
+ if (item == null || isNaN(item.Value) || isNaN(item.Value2)) continue;
+ if (item.Color == null) continue;
+
+ let valueMax = Math.max(item.Value, item.Value2);
+ let valueMin = Math.min(item.Value, item.Value2);
+
+ let yTop = this.ChartFrame.GetYFromData(valueMax);
+ let yBottom = this.ChartFrame.GetYFromData(valueMin);
+
+ if (item.Title && item.TitleColor)
+ {
+ let x = xRight;
+ if (item.Align == 'left')
+ {
+ this.Canvas.textAlign = 'left';
+ x = left;
+ }
+ else
+ {
+ this.Canvas.textAlign = 'right';
+ x = xRight;
+ }
+
+ this.Canvas.textBaseline = 'middle';
+ this.Canvas.fillStyle = item.TitleColor;
+ this.Canvas.font = this.Font;
+ let y = yTop + (yBottom - yTop) / 2;
+ this.Canvas.fillText(item.Title, x, y);
+ }
+ }
+ }
+
+ this.HScreenDraw = function ()
+ {
+ var bottom = this.ChartBorder.GetBottom();
+ var top = this.ChartBorder.GetTop();
+ var height = this.ChartBorder.GetHeight();
+
+ for (let i in this.Data.Data)
+ {
+ let item = this.Data.Data[i];
+ if (item == null || isNaN(item.Value) || isNaN(item.Value2)) continue;
+ if (item.Color == null) continue;
+
+ let valueMax = Math.max(item.Value, item.Value2);
+ let valueMin = Math.min(item.Value, item.Value2);
+
+ var yTop = this.ChartFrame.GetYFromData(valueMax);
+ var yBottom = this.ChartFrame.GetYFromData(valueMin);
+
+ this.Canvas.fillStyle = item.Color;
+ this.Canvas.fillRect(ToFixedRect(yBottom), ToFixedRect(top), ToFixedRect(yTop - yBottom), ToFixedRect(height));
+
+ if (item.Title && item.TitleColor)
+ {
+ var xText = yTop + (yBottom - yTop) / 2;
+ var yText = bottom;
+ this.Canvas.save();
+ this.Canvas.translate(xText, yText);
+ this.Canvas.rotate(90 * Math.PI / 180);
+
+ this.Canvas.textAlign = 'right';
+ this.Canvas.textBaseline = 'middle';
+ this.Canvas.fillStyle = item.TitleColor;
+ this.Canvas.font = this.Font;
+ this.Canvas.fillText(item.Title, 0, -2);
+
+ this.Canvas.restore();
+ }
+ }
+ }
+
+ this.GetMaxMin = function ()
+ {
+ var xPointCount = this.ChartFrame.XPointCount;
+ var range = {};
+ range.Min = null;
+ range.Max = null;
+
+ if (!this.Data || !this.Data.Data) return range;
+
+ for (let i in this.Data.Data)
+ {
+ let item = this.Data.Data[i];
+ if (item == null || isNaN(item.Value) || isNaN(item.Value2)) continue;
+
+ let valueMax = Math.max(item.Value, item.Value2);
+ let valueMin = Math.min(item.Value, item.Value2);
+
+ if (range.Max == null) range.Max = valueMax;
+ if (range.Min == null) range.Min = valueMin;
+
+ if (range.Max < valueMax) range.Max = valueMax;
+ if (range.Min > valueMin) range.Min = valueMin;
+ }
+ return range;
+ }
+}
+
+// 面积图
+function ChartBand() {
+ this.newMethod = IChartPainting; //派生
+ this.newMethod();
+ delete this.newMethod;
+ this.IsDrawFirst = true;
+
+ this.FirstColor = g_JSChartResource.Index.LineColor[0];
+ this.SecondColor = g_JSChartResource.Index.LineColor[1];
+
+ this.Draw = function ()
+ {
+ if (this.ChartFrame.IsMinSize) return;
+ if (this.NotSupportMessage)
+ {
+ this.DrawNotSupportmessage();
+ return;
+ }
+
+ var dataWidth = this.ChartFrame.DataWidth;
+ var distanceWidth = this.ChartFrame.DistanceWidth;
+ var xPointCount = this.ChartFrame.XPointCount;
+ var xOffset = this.ChartBorder.GetLeft() + distanceWidth / 2.0 + 2.0;
+ var x = 0;
+ var y = 0;
+ var y2 = 0;
+ var firstlinePoints = [];
+ var secondlinePoints = [];
+ var lIndex = 0;
+ for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth))
+ {
+ var value = this.Data.Data[i];
+ if (value == null || value.Value == null || value.Value2 == null) continue;
+ x = this.ChartFrame.GetXFromIndex(j);
+ y = this.ChartFrame.GetYFromData(value.Value);
+ y2 = this.ChartFrame.GetYFromData(value.Value2);
+ firstlinePoints[lIndex] = { x: x, y: y };
+ secondlinePoints[lIndex] = { x: x, y: y2 };
+ lIndex++;
+ }
+
+ if (firstlinePoints.length > 1)
+ {
+ this.Canvas.save();
+ this.Canvas.beginPath();
+ for (var i = 0; i < firstlinePoints.length; ++i)
+ {
+ if (i == 0)
+ this.Canvas.moveTo(firstlinePoints[i].x, firstlinePoints[i].y);
+ else
+ this.Canvas.lineTo(firstlinePoints[i].x, firstlinePoints[i].y);
+ }
+ for (var j = secondlinePoints.length - 1; j >= 0; --j)
+ {
+ this.Canvas.lineTo(secondlinePoints[j].x, secondlinePoints[j].y);
+ }
+ this.Canvas.closePath();
+ this.Canvas.strokeStyle = "rgba(255,255,255,0)";
+ this.Canvas.stroke();
+ this.Canvas.clip();
+ this.Canvas.beginPath();
+ this.Canvas.moveTo(firstlinePoints[0].x, this.ChartBorder.GetBottom());
+ for (var i = 0; i < firstlinePoints.length; ++i)
+ {
+ this.Canvas.lineTo(firstlinePoints[i].x, firstlinePoints[i].y);
+ }
+ this.Canvas.lineTo(firstlinePoints[firstlinePoints.length - 1].x, this.ChartBorder.GetBottom());
+ this.Canvas.closePath();
+ this.Canvas.fillStyle = this.FirstColor;
+ this.Canvas.fill();
+ this.Canvas.beginPath();
+ this.Canvas.moveTo(secondlinePoints[0].x, this.ChartBorder.GetBottom());
+ for (var i = 0; i < secondlinePoints.length; ++i)
+ {
+ this.Canvas.lineTo(secondlinePoints[i].x, secondlinePoints[i].y);
+ }
+ this.Canvas.lineTo(secondlinePoints[secondlinePoints.length - 1].x, this.ChartBorder.GetBottom());
+ this.Canvas.closePath();
+ this.Canvas.fillStyle = this.SecondColor;
+ this.Canvas.fill();
+ this.Canvas.restore();
+ }
+ }
+
+ this.GetMaxMin = function ()
+ {
+ var xPointCount = this.ChartFrame.XPointCount;
+ var range = {};
+ range.Min = null;
+ range.Max = null;
+
+ for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j)
+ {
+ var value = this.Data.Data[i];
+ if (value == null || value.Value == null || value.Value2 == null) continue;
+ var maxData = value.Value > value.Value2 ? value.Value : value.Value2;
+ var minData = value.Value < value.Value2 ? value.Value : value.Value2;
+ if (range.Max == null)
+ range.Max = maxData;
+ else if (range.Max < maxData)
+ range.Max = maxData;
+
+ if (range.Min == null)
+ range.Min = minData;
+ else if (range.Min > minData)
+ range.Min = minData;
+ }
+ return range;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// 其他图形
+//
+//
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/*
+ 饼图
+*/
+function ChartPie()
+{
+ this.newMethod = IChartPainting; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.Draw = function ()
+ {
+ if (!this.Data || !this.Data.Data || !(this.Data.Data.length > 0)) return this.DrawEmptyData();
+
+ let left = this.ChartBorder.GetLeft();
+ let right = this.ChartBorder.GetRight();
+ let top = this.ChartBorder.GetTop();
+ let bottom = this.ChartBorder.GetBottom();
+ let width = this.ChartBorder.GetWidth();
+ let height = this.ChartBorder.GetHeight();
+
+ //圆半径
+ let radius = width / 4 * 0.8;
+ this.Canvas.save();
+ this.Canvas.translate(left + radius, top + height / 2);
+
+ let totalValue = 0; //求和
+ for (let i in this.Data.Data) {
+ totalValue += this.Data.Data[i].Value;
+ }
+
+ let startAngle = Math.PI * 1.5;
+ let start = startAngle;
+ let end = startAngle;
+ //画饼图
+ for (let i in this.Data.Data)
+ {
+ let item = this.Data.Data[i];
+ let rate = item.Value / totalValue; //占比
+
+ // 绘制扇形
+ this.Canvas.beginPath();
+ this.Canvas.moveTo(0, 0);
+
+ end += rate * 2 * Math.PI;//终止角度
+ this.Canvas.strokeStyle = "white";
+ this.Canvas.fillStyle = item.Color;
+ this.Canvas.arc(0, 0, radius, start, end);
+ this.Canvas.fill();
+ this.Canvas.closePath();
+ this.Canvas.stroke();
+
+ start += rate * 2 * Math.PI;//起始角度
+ }
+
+ //画文字
+ this.Canvas.restore();
+ let textLeft = left + width / 2 + 5;
+ // let textTop = top + height / 2 + 20;
+ let textTop = top;
+ this.Canvas.textBaseline = "bottom";
+ this.Canvas.font = "12px 微软雅黑";
+
+ for (let i = 0, j = 0; i < this.Data.Data.length; ++i)
+ {
+ let item = this.Data.Data[i];
+ if (!item.Text) continue;
+
+ this.Canvas.fillStyle = item.Color;
+ this.Canvas.fillRect(textLeft, textTop - 15, 13, 13);
+
+ this.Canvas.fillStyle = 'rgb(102,102,102)';
+ this.Canvas.fillText(item.Text, textLeft + 16, textTop);
+ // textTop += 20;
+ textTop += 17;
+ if (textTop > top + height / 2 + radius) {
+ ++j;
+ if (j >= 2) break;
+
+ // textTop = top + height / 2 + 20;
+ textTop = top;
+ textLeft = right - (width / 4) + 5;
+ }
+ }
+ }
+
+ //空数据
+ this.DrawEmptyData = function ()
+ {
+ console.log('[ChartPie::DrawEmptyData]')
+
+ let left = this.ChartBorder.GetLeft();
+ let right = this.ChartBorder.GetRight();
+ let top = this.ChartBorder.GetTop();
+ let bottom = this.ChartBorder.GetBottom();
+ let width = this.ChartBorder.GetWidth();
+ let height = this.ChartBorder.GetHeight();
+
+ //圆半径
+ let radius = width / 4 * 0.8;
+ this.Canvas.save();
+ this.Canvas.translate(left + radius, top + height / 2);
+
+ this.Canvas.beginPath();
+ this.Canvas.fillStyle = 'rgb(211,211,211)';
+ this.Canvas.strokeStyle = "white";
+ this.Canvas.arc(0, 0, radius * 0.8, 0, 2 * Math.PI);
+ this.Canvas.fill();
+ this.Canvas.closePath();
+ this.Canvas.stroke();
+
+ this.Canvas.restore();
+ }
+}
+
+
+/*
+ 圆环
+*/
+function ChartCircle()
+{
+ this.newMethod = IChartPainting; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.BGColor = 'white'; //背景色
+ this.TextHeight = 25;
+
+ //空数据
+ this.DrawEmptyData = function ()
+ {
+ console.log('[ChartCircle::DrawEmptyData]')
+ }
+
+ this.Draw = function ()
+ {
+ if (!this.Data || !this.Data.Data || !(this.Data.Data.length > 0)) return this.DrawEmptyData();
+
+ let left = this.ChartBorder.GetLeft();
+ let right = this.ChartBorder.GetRight();
+ let top = this.ChartBorder.GetTop();
+ let bottom = this.ChartBorder.GetBottom();
+ let width = this.ChartBorder.GetWidth();
+ let height = this.ChartBorder.GetHeight();
+
+ //圆半径
+ let lTextHeight = this.TextHeight;
+ let size = width - lTextHeight;
+ if (size > height - lTextHeight) size = height - lTextHeight;
+ let radius = (size - lTextHeight) / 2;
+ this.Canvas.save();
+ this.Canvas.translate(left + width / 2, top + height / 2 - lTextHeight / 2);
+
+ let totalValue = 0; //求和
+ for (let i in this.Data.Data)
+ {
+ totalValue += this.Data.Data[i].Value;
+ }
+
+ let startAngle = Math.PI * 1.5;
+ let start = startAngle;
+ let end = startAngle;
+ //画饼图
+ for (let i in this.Data.Data)
+ {
+ let item = this.Data.Data[i];
+ let rate = item.Value / totalValue; //占比
+ //console.log('[ChartPie::Draw]', i, rate, item);
+
+ // 绘制扇形
+ this.Canvas.beginPath();
+ this.Canvas.moveTo(0, 0);
+
+ end += rate * 2 * Math.PI;//终止角度
+ this.Canvas.strokeStyle = "white";
+ this.Canvas.fillStyle = item.Color;
+ this.Canvas.arc(0, 0, radius, start, end);
+ this.Canvas.fill();
+ this.Canvas.closePath();
+ this.Canvas.stroke();
+
+ start += rate * 2 * Math.PI;//起始角度
+ }
+
+ //中心画一个背景色的圆
+ this.Canvas.beginPath();
+ this.Canvas.fillStyle = this.BGColor;
+ this.Canvas.arc(0, 0, radius * 0.5, 0, 2 * Math.PI);
+ this.Canvas.fill();
+ this.Canvas.closePath();
+ this.Canvas.stroke();
+
+ this.Canvas.restore();
+
+ //画文字
+ this.Canvas.restore();
+ let textLeft = left;
+ let textTop = top + height / 2 - lTextHeight / 2 + radius + 5 + 20;
+ this.Canvas.textBaseline = "bottom";
+ this.Canvas.textAlign = 'left';
+ this.Canvas.font = "14px 微软雅黑";
+ let textWidth = 0;
+ //以圆心左右显示
+ for (let i = 0, j = 0; i < this.Data.Data.length; ++i)
+ {
+ let item = this.Data.Data[i];
+ if (!item.Text) continue;
+
+ this.Canvas.fillStyle = item.Color;
+
+ if (j % 2 == 0)
+ {
+ textLeft = left + width / 2 - 10;
+ textWidth = this.Canvas.measureText(item.Text).width;
+ textLeft = textLeft - textWidth - 16;
+ this.Canvas.fillRect(textLeft, textTop - 15, 13, 13);
+ this.Canvas.fillStyle = 'rgb(102,102,102)';
+ this.Canvas.fillText(item.Text, textLeft + 16, textTop);
+ }
+ else
+ {
+ textLeft = left + width / 2 + 10 + 10;
+ this.Canvas.fillRect(textLeft, textTop - 15, 13, 13);
+ this.Canvas.fillStyle = 'rgb(102,102,102)';
+ this.Canvas.fillText(item.Text, textLeft + 16, textTop);
+ textTop += 20;
+ }
+
+ if (textTop > bottom) break;
+
+ ++j;
+ }
+ }
+}
+
+
+
+// 中国地图
+function ChartChinaMap()
+{
+ this.newMethod = IChartPainting; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.ImageData = null;
+ this.Left;
+ this.Top;
+ this.Width;
+ this.Height;
+ this.ImageWidth;
+ this.ImageHeight;
+
+ this.DefaultColor = [217, 222, 239];
+
+ this.Color =
+ [
+ { Name: '海南', Color: 'rgb(217,222,223)' },
+ { Name: '内蒙古', Color: 'rgb(217,222,225)' },
+ { Name: '新疆', Color: 'rgb(217,222,226)' },
+ { Name: '青海', Color: 'rgb(217,222,227)' },
+ { Name: '西藏', Color: 'rgb(217,222,228)' },
+ { Name: '云南', Color: 'rgb(217,222,229)' },
+ { Name: '黑龙江', Color: 'rgb(217,222,230)' },
+ { Name: '吉林', Color: 'rgb(217,222,231)' },
+ { Name: '辽宁', Color: 'rgb(217,222,232)' },
+ { Name: '河北', Color: 'rgb(217,222,233)' },
+ { Name: '山东', Color: 'rgb(217,222,234)' },
+ { Name: '江苏', Color: 'rgb(217,222,235)' },
+ { Name: '浙江', Color: 'rgb(217,222,236)' },
+ { Name: '福建', Color: 'rgb(217,222,237)' },
+ { Name: '广东', Color: 'rgb(217,222,238)' },
+ { Name: '广西', Color: 'rgb(217,222,239)' },
+ { Name: '贵州', Color: 'rgb(217,222,240)' },
+ { Name: '湖南', Color: 'rgb(217,222,241)' },
+ { Name: '江西', Color: 'rgb(217,222,242)' },
+ { Name: '安徽', Color: 'rgb(217,222,243)' },
+ { Name: '湖北', Color: 'rgb(217,222,244)' },
+ { Name: '重庆', Color: 'rgb(217,222,245)' },
+ { Name: '四川', Color: 'rgb(217,222,246)' },
+ { Name: '甘肃', Color: 'rgb(217,222,247)' },
+ { Name: '陕西', Color: 'rgb(217,222,248)' },
+ { Name: '山西', Color: 'rgb(217,222,249)' },
+ { Name: '河南', Color: 'rgb(217,222,250)' }
+ ];
+
+ this.Draw = function ()
+ {
+ let left = this.ChartBorder.GetLeft() + 1;
+ let right = this.ChartBorder.GetRight() - 1;
+ let top = this.ChartBorder.GetTop() + 1;
+ let bottom = this.ChartBorder.GetBottom() - 1;
+ let width = this.ChartBorder.GetWidth() - 2;
+ let height = this.ChartBorder.GetHeight() - 2;
+
+ let imageWidth = CHINA_MAP_IMAGE.width;
+ let imageHeight = CHINA_MAP_IMAGE.height;
+
+ let drawImageWidth = imageWidth;
+ let drawImageHeight = imageHeight;
+
+ if (height < drawImageHeight || width < drawImageWidth)
+ {
+ this.ImageData = null;
+ return;
+ }
+
+ if (this.Left != left || this.Top != top || this.Width != width || this.Height != height || this.ImageWidth != imageWidth || this.ImageHeight != imageHeight)
+ {
+ this.ImageData = null;
+
+ this.ImageWidth = imageWidth;
+ this.ImageHeight = imageHeight;
+ this.Left = left;
+ this.Top = top;
+ this.Width = width;
+ this.Height = height;
+
+ console.log(imageWidth, imageHeight);
+ }
+
+ if (this.ImageData == null)
+ {
+ this.Canvas.drawImage(CHINA_MAP_IMAGE, 0, 0, imageWidth, imageHeight, left, top, drawImageWidth, drawImageHeight);
+ this.ImageData = this.Canvas.getImageData(left, top, drawImageWidth, drawImageHeight);
+
+ let defaultColorSet = new Set(); //默认颜色填充的色块
+ let colorMap = new Map(); //定义颜色填充的色块
+
+ let nameMap = new Map();
+ if (this.Data.length > 0)
+ {
+ for (let i in this.Data)
+ {
+ let item = this.Data[i];
+ nameMap.set(item.Name, item.Color)
+ }
+ }
+
+ console.log(this.Data);
+ for (let i in this.Color)
+ {
+ let item = this.Color[i];
+ if (nameMap.has(item.Name))
+ {
+ colorMap.set(item.Color, nameMap.get(item.Name));
+ }
+ else
+ {
+ defaultColorSet.add(item.Color);
+ }
+ }
+
+ var color;
+ for (let i = 0; i < this.ImageData.data.length; i += 4)
+ {
+ color = 'rgb(' + this.ImageData.data[i] + ',' + this.ImageData.data[i + 1] + ',' + this.ImageData.data[i + 2] + ')';
+
+ if (defaultColorSet.has(color))
+ {
+ this.ImageData.data[i] = this.DefaultColor[0];
+ this.ImageData.data[i + 1] = this.DefaultColor[1];
+ this.ImageData.data[i + 2] = this.DefaultColor[2];
+ }
+ else if (colorMap.has(color))
+ {
+ let colorValue = colorMap.get(color);
+ this.ImageData.data[i] = colorValue[0];
+ this.ImageData.data[i + 1] = colorValue[1];
+ this.ImageData.data[i + 2] = colorValue[2];
+ }
+ }
+ this.Canvas.clearRect(left, top, drawImageWidth, drawImageHeight);
+ this.Canvas.putImageData(this.ImageData, left, top, 0, 0, drawImageWidth, drawImageHeight);
+ }
+ else
+ {
+ this.Canvas.putImageData(this.ImageData, left, top, 0, 0, drawImageWidth, drawImageHeight);
+ }
+ }
+}
+
+
+// 雷达图
+function ChartRadar()
+{
+ this.newMethod = IChartPainting; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.BorderPoint = []; //边框点
+ this.DataPoint = []; //数据点
+ this.CenterPoint = {};
+ this.StartAngle = 0;
+ this.Color = 'rgb(198,198,198)';
+ this.AreaColor = 'rgba(242,154,118,0.4)'; //面积图颜色
+ this.AreaLineColor = 'rgb(242,154,118)';
+ this.TitleFont = '24px 微软雅黑';
+ this.TitleColor = 'rgb(102,102,102)';
+ this.BGColor = ['rgb(255,255,255)', 'rgb(224,224,224)']//背景色
+
+ this.DrawBorder = function () //画边框
+ {
+ if (this.BorderPoint.length <= 0) return;
+
+ this.Canvas.font = this.TitleFont;
+ this.Canvas.strokeStyle = this.Color;
+
+ const aryBorder = [1, 0.8, 0.6, 0.4, 0.2];
+ for (let j in aryBorder)
+ {
+ var rate = aryBorder[j];
+ var isFirstDraw = true;
+ for (let i in this.BorderPoint)
+ {
+ var item = this.BorderPoint[i];
+ item.X = this.CenterPoint.X + item.Radius * Math.cos(item.Angle * Math.PI / 180) * rate;
+ item.Y = this.CenterPoint.Y + item.Radius * Math.sin(item.Angle * Math.PI / 180) * rate;
+ if (isFirstDraw)
+ {
+ this.Canvas.beginPath();
+ this.Canvas.moveTo(item.X, item.Y);
+ isFirstDraw = false;
+ }
+ else
+ {
+ this.Canvas.lineTo(item.X, item.Y);
+ }
+
+ if (j == 0) this.DrawText(item);
+ }
+
+ this.Canvas.closePath();
+ this.Canvas.stroke();
+ this.Canvas.fillStyle = this.BGColor[j % 2 == 0 ? 0 : 1];
+ this.Canvas.fill();
+ }
+
+ this.Canvas.beginPath();
+ for (let i in this.BorderPoint)
+ {
+ var item = this.BorderPoint[i];
+ item.X = this.CenterPoint.X + item.Radius * Math.cos(item.Angle * Math.PI / 180);
+ item.Y = this.CenterPoint.Y + item.Radius * Math.sin(item.Angle * Math.PI / 180);
+ this.Canvas.moveTo(this.CenterPoint.X, this.CenterPoint.Y);
+ this.Canvas.lineTo(item.X, item.Y);
+ }
+ this.Canvas.stroke();
+ }
+
+ this.DrawArea = function ()
+ {
+ if (!this.DataPoint || this.DataPoint.length <= 0) return;
+
+ this.Canvas.fillStyle = this.AreaColor;
+ this.Canvas.strokeStyle = this.AreaLineColor;
+ this.Canvas.beginPath();
+ var isFirstDraw = true;
+ for (let i in this.DataPoint)
+ {
+ var item = this.DataPoint[i];
+ if (isFirstDraw)
+ {
+ this.Canvas.beginPath();
+ this.Canvas.moveTo(item.X, item.Y);
+ isFirstDraw = false;
+ }
+ else
+ {
+ this.Canvas.lineTo(item.X, item.Y);
+ }
+ }
+
+ this.Canvas.closePath();
+ this.Canvas.fill();
+ this.Canvas.stroke();
+ }
+
+ this.DrawText = function (item)
+ {
+ if (!item.Text) return;
+
+ //console.log(item.Text, item.Angle);
+ this.Canvas.fillStyle = this.TitleColor;
+ var xText = item.X, yText = item.Y;
+
+ //显示每个角度的位置
+ if (item.Angle > 0 && item.Angle < 45)
+ {
+ this.Canvas.textAlign = 'left';
+ this.Canvas.textBaseline = 'middle';
+ xText += 2;
+ }
+ else if (item.Angle >= 0 && item.Angle < 90) {
+ this.Canvas.textAlign = 'left';
+ this.Canvas.textBaseline = 'top';
+ xText += 2;
+ }
+ else if (item.Angle >= 90 && item.Angle < 135)
+ {
+ this.Canvas.textAlign = 'right';
+ this.Canvas.textBaseline = 'top';
+ xText -= 2;
+ }
+ else if (item.Angle >= 135 && item.Angle < 180)
+ {
+ this.Canvas.textAlign = 'right';
+ this.Canvas.textBaseline = 'top';
+ xText -= 2;
+ }
+ else if (item.Angle >= 180 && item.Angle < 225) {
+ this.Canvas.textAlign = 'right';
+ this.Canvas.textBaseline = 'middle';
+ xText -= 2;
+ }
+ else if (item.Angle >= 225 && item.Angle <= 270) {
+ this.Canvas.textAlign = 'center';
+ this.Canvas.textBaseline = 'bottom';
+ }
+ else if (item.Angle > 270 && item.Angle < 315)
+ {
+ this.Canvas.textAlign = 'left';
+ this.Canvas.textBaseline = 'bottom';
+ xText += 2;
+ }
+ else
+ {
+ this.Canvas.textAlign = 'left';
+ this.Canvas.textBaseline = 'middle';
+ xText += 2;
+ }
+
+ this.Canvas.fillText(item.Text, xText, yText);
+ }
+
+ this.Draw = function ()
+ {
+ this.BorderPoint = [];
+ this.DataPoint = [];
+ this.InternalBorderPoint = [];
+ this.CenterPoint = {};
+ if (!this.Data || !this.Data.Data || !(this.Data.Data.length > 0))
+ this.CalculatePoints(null);
+ else
+ this.CalculatePoints(this.Data.Data);
+
+ this.DrawBorder();
+ this.DrawArea();
+ }
+
+ this.CalculatePoints = function (data)
+ {
+ let left = this.ChartBorder.GetLeft();
+ let right = this.ChartBorder.GetRight();
+ let top = this.ChartBorder.GetTop();
+ let bottom = this.ChartBorder.GetBottom();
+ let width = this.ChartBorder.GetWidth();
+ let height = this.ChartBorder.GetHeight();
+
+ let ptCenter = { X: left + width / 2, Y: top + height / 2 }; //中心点
+ let radius = Math.min(width / 2, height / 2) - 2 //半径
+ let count = Math.max(5, data ? data.length : 0);
+ let averageAngle = 360 / count;
+ for (let i = 0; i < count; ++i)
+ {
+ let ptBorder = { Index: i, Radius: radius, Angle: i * averageAngle + this.StartAngle };
+ let angle = ptBorder.Angle;
+
+ if (data && i < data.length)
+ {
+ var item = data[i];
+ let ptData = { Index: i, Text: item.Text };
+ ptBorder.Text = item.Name;
+ if (!item.Value)
+ {
+ ptData.X = ptCenter.X;
+ ptData.Y = ptCenter.Y;
+ }
+ else
+ {
+ var value = item.Value;
+ if (value >= 1) value = 1;
+ var dataRadius = radius * value;
+ ptData.X = ptCenter.X + dataRadius * Math.cos(angle * Math.PI / 180);
+ ptData.Y = ptCenter.Y + dataRadius * Math.sin(angle * Math.PI / 180);
+ }
+
+ this.DataPoint.push(ptData);
+ }
+
+ this.BorderPoint.push(ptBorder);
+ }
+ this.CenterPoint = ptCenter;
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+//十字光标
+function ChartCorssCursor()
+{
+ this.Frame;
+ this.Canvas; //画布
+
+ this.HPenColor = g_JSChartResource.CorssCursorHPenColor; //水平线颜色
+ this.HPenType = 0; //水平线样式 0=虚线 1=实线
+
+ this.VPenColor = g_JSChartResource.CorssCursorVPenColor; //垂直线颜色
+ this.VPenType = 0; //垂直线颜色 0=虚线 1=实线 2=K线宽度
+
+ this.Font = g_JSChartResource.CorssCursorTextFont; //字体
+ this.TextColor = g_JSChartResource.CorssCursorTextColor; //文本颜色
+ this.TextBGColor = g_JSChartResource.CorssCursorBGColor; //文本背景色
+ this.TextHeight = 15; //文本字体高度
+ this.LastPoint;
+ this.CursorIndex; //当前数据的位置
+
+ this.PointX;
+ this.PointY;
+
+ this.StringFormatX;
+ this.StringFormatY;
+
+ this.IsShow = true; //是否显示
+ this.ShowTextMode = { Left: 1, Right: 1, Bottom: 1 }; //0=不显示 1=显示在框架外 2=显示在框架内
+ this.IsShowCorss = true; //是否显示十字光标
+ this.IsShowClose = false; //Y轴始终显示收盘价
+ this.IsFixXLastTime=false; //是否修正X轴,超出当前时间的,X轴调整到当前最后的时间.
+
+ //内部使用
+ this.Close = null; //收盘价格
+
+ this.GetCloseYPoint = function (index)
+ {
+ this.Close = null;
+ if (!this.StringFormatX.Data) return null;
+ var data = this.StringFormatX.Data;
+ if (!data.Data || data.Data.length <= 0) return null;
+ var dataIndex = data.DataOffset + index;
+ if (dataIndex >= data.Data.length) dataIndex = data.Data.length - 1;
+ if (dataIndex < 0) return null;
+
+ var klineData = data.Data[dataIndex];
+ if (!klineData) return null;
+ this.Close = klineData.Close;
+ var yPoint = this.Frame.GetYFromData(this.Close);
+ return yPoint;
+ }
+
+ this.FixMinuteLastTimeXPoint=function(index)
+ {
+ if (!IFrameSplitOperator.IsNumber(index)) return null;
+ index=parseInt(index);
+ if (!this.StringFormatX.Data) return null;
+ var data = this.StringFormatX.Data;
+ if (!data.Data || data.Data.length <= 0) return null;
+ var dataIndex = data.DataOffset + index;
+ if (dataIndex 2) this.Canvas.lineWidth = barWidth;
+ }
+
+ this.Canvas.beginPath();
+ if (this.Frame.SubFrame.length > 0)
+ {
+ for (var i in this.Frame.SubFrame)
+ {
+ var frame = this.Frame.SubFrame[i].Frame;
+ top = frame.ChartBorder.GetTopTitle();
+ bottom = frame.ChartBorder.GetBottom();
+ this.Canvas.moveTo(ToFixedPoint(x), top);
+ this.Canvas.lineTo(ToFixedPoint(x), bottom);
+ }
+ }
+ else
+ {
+ this.Canvas.moveTo(ToFixedPoint(x), top);
+ this.Canvas.lineTo(ToFixedPoint(x), bottom);
+ }
+
+ this.Canvas.stroke();
+ this.Canvas.restore();
+ }
+
+ var xValue = this.Frame.GetXData(x);
+ var yValueExtend = {};
+ var yValue = this.Frame.GetYData(y, yValueExtend);
+ this.StringFormatY.RValue = yValueExtend.RightYValue; //右侧子坐标
+ if (this.IsShowClose && this.Close != null) yValue = this.Close;
+
+ this.StringFormatX.Value = this.CursorIndex;
+ this.StringFormatY.Value = yValue;
+ this.StringFormatY.FrameID = yValueExtend.FrameID;
+
+ if (((this.ShowTextMode.Left == 1 && this.Frame.ChartBorder.Left >= 30) || this.ShowTextMode.Left == 2 ||
+ (this.ShowTextMode.Right == 1 && this.Frame.ChartBorder.Right >= 30) || this.ShowTextMode.Right == 2) && this.StringFormatY.Operator())
+ {
+ var text = this.StringFormatY.Text;
+ this.Canvas.font = this.Font;
+ var textWidth = this.Canvas.measureText(text).width + 4; //前后各空2个像素
+
+ if (this.Frame.ChartBorder.Left >= 30 && this.ShowTextMode.Left == 1)
+ {
+ this.Canvas.fillStyle = this.TextBGColor;
+ if (left < textWidth) //左边空白的地方太少了画布下
+ {
+ this.Canvas.fillRect(2, y - this.TextHeight / 2, textWidth, this.TextHeight);
+ this.Canvas.textAlign = "left";
+ this.Canvas.textBaseline = "middle";
+ this.Canvas.fillStyle = this.TextColor;
+ this.Canvas.fillText(text, 2 + 2, y, textWidth);
+ }
+ else
+ {
+ this.Canvas.fillRect(left - 2, y - this.TextHeight / 2, -textWidth, this.TextHeight);
+ this.Canvas.textAlign = "right";
+ this.Canvas.textBaseline = "middle";
+ this.Canvas.fillStyle = this.TextColor;
+ this.Canvas.fillText(text, left - 4, y, textWidth);
+ }
+ }
+ else if (this.ShowTextMode.Left == 2)
+ {
+ this.Canvas.fillStyle = this.TextBGColor;
+ this.Canvas.fillRect(left, y - this.TextHeight / 2, textWidth, this.TextHeight);
+ this.Canvas.textAlign = "left";
+ this.Canvas.textBaseline = "middle";
+ this.Canvas.fillStyle = this.TextColor;
+ this.Canvas.fillText(text, left + 2, y, textWidth);
+ }
+
+ if (this.StringFormatY.RText)
+ {
+ text = this.StringFormatY.RText;
+ var textWidth = this.Canvas.measureText(text).width + 4; //前后各空2个像素
+ }
+
+ if (this.Frame.ChartBorder.Right >= 30 && this.ShowTextMode.Right == 1)
+ {
+ this.Canvas.fillStyle = this.TextBGColor;
+ if (rightWidth > textWidth) //右边不够就不画
+ {
+ this.Canvas.fillRect(right + 2, y - this.TextHeight / 2, textWidth, this.TextHeight);
+ this.Canvas.textAlign = "left";
+ this.Canvas.textBaseline = "middle";
+ this.Canvas.fillStyle = this.TextColor;
+ this.Canvas.fillText(text, right + 4, y, textWidth);
+ }
+ else
+ {
+ this.Canvas.fillRect(chartRight - 2 - textWidth, y - this.TextHeight / 2, textWidth, this.TextHeight);
+ this.Canvas.textAlign = "right";
+ this.Canvas.textBaseline = "middle";
+ this.Canvas.fillStyle = this.TextColor;
+ this.Canvas.fillText(text, chartRight - 4, y, textWidth);
+ }
+ }
+ else if (this.ShowTextMode.Right == 2)
+ {
+ this.Canvas.fillStyle = this.TextBGColor;
+ var showLeft = right - textWidth;
+ this.Canvas.fillRect(showLeft, y - this.TextHeight / 2, textWidth, this.TextHeight);
+ this.Canvas.textAlign = "left";
+ this.Canvas.textBaseline = "middle";
+ this.Canvas.fillStyle = this.TextColor;
+ this.Canvas.fillText(text, showLeft + 2, y, textWidth);
+ }
+ }
+
+ if (this.ShowTextMode.Bottom == 1 && this.StringFormatX.Operator())
+ {
+ var text = this.StringFormatX.Text;
+ this.Canvas.font = this.Font;
+
+ this.Canvas.fillStyle = this.TextBGColor;
+ var textWidth = this.Canvas.measureText(text).width + 4; //前后各空2个像素
+ if (x - textWidth / 2 < 3) //左边位置不够了, 顶着左边画
+ {
+ this.Canvas.fillRect(x - 1, bottom + 2, textWidth, this.TextHeight);
+ this.Canvas.textAlign = "left";
+ this.Canvas.textBaseline = "top";
+ this.Canvas.fillStyle = this.TextColor;
+ this.Canvas.fillText(text, x + 1, bottom + 2, textWidth);
+ }
+ else if ((right - left) - x < textWidth)
+ { //右边位置不够用,顶着右边画
+ this.Canvas.fillRect(x - textWidth, bottom + 2, textWidth, this.TextHeight);
+ this.Canvas.textAlign = "right";
+ this.Canvas.textBaseline = "top";
+ this.Canvas.fillStyle = this.TextColor;
+ this.Canvas.fillText(text, x - 1, bottom + 2, textWidth);
+ }
+ else
+ {
+ this.Canvas.fillRect(x - textWidth / 2, bottom + 2, textWidth, this.TextHeight);
+ this.Canvas.textAlign = "center";
+ this.Canvas.textBaseline = "top";
+ this.Canvas.fillStyle = this.TextColor;
+ this.Canvas.fillText(text, x, bottom + 2, textWidth);
+ }
+ }
+ }
+
+ this.HScreenDraw = function ()
+ {
+ var x = this.LastPoint.X;
+ var y = this.LastPoint.Y;
+
+ y = this.Frame.GetXFromIndex(this.CursorIndex); //手机端 十字只能画在K线上
+
+ var left = this.Frame.ChartBorder.GetLeft();
+ var right = this.Frame.ChartBorder.GetRightEx();
+ var top = this.Frame.ChartBorder.GetTop();
+ var bottom = this.Frame.ChartBorder.GetBottom();
+ var bottomWidth = this.Frame.ChartBorder.Bottom;
+
+ this.PointY = [[left, y], [right, y]];
+ this.PointX = [[x, top], [x, bottom]];
+
+ if (this.IsShowCorss) //十字线
+ {
+ this.Canvas.save();
+ this.Canvas.strokeStyle = this.HPenColor;
+ if (this.HPenType == 0) this.Canvas.setLineDash([3, 2]); //虚线
+
+ //画竖线
+ this.Canvas.beginPath();
+ this.Canvas.moveTo(ToFixedPoint(x), top);
+ this.Canvas.lineTo(ToFixedPoint(x), bottom);
+ this.Canvas.stroke();
+ this.Canvas.restore();
+
+ this.Canvas.save();
+ this.Canvas.strokeStyle = this.VPenColor;
+ if (this.VPenType == 0)
+ {
+ this.Canvas.setLineDash([3, 2]); //虚线
+ }
+ else if (this.VPenType == 2)
+ {
+ let barWidth = this.Frame.SubFrame[0].Frame.DataWidth; //和K线一样宽度
+ if (barWidth > 2) this.Canvas.lineWidth = barWidth;
+ }
+ this.Canvas.beginPath();
+ //画横线
+ if (this.Frame.SubFrame.length > 0)
+ {
+ for (var i in this.Frame.SubFrame)
+ {
+ var frame = this.Frame.SubFrame[i].Frame;
+ this.Canvas.moveTo(frame.ChartBorder.GetLeft(), ToFixedPoint(y));
+ this.Canvas.lineTo(frame.ChartBorder.GetRightTitle(), ToFixedPoint(y));
+ }
+ }
+ else
+ {
+ this.Canvas.moveTo(left, ToFixedPoint(y));
+ this.Canvas.lineTo(right, ToFixedPoint(y));
+ }
+
+ this.Canvas.stroke();
+ this.Canvas.restore();
+ }
+
+ var xValue = this.Frame.GetXData(y);
+ var yValueExtend = {};
+ var yValue = this.Frame.GetYData(x, yValueExtend);
+
+ this.StringFormatX.Value = xValue;
+ this.StringFormatY.Value = yValue;
+ this.StringFormatY.FrameID = yValueExtend.FrameID;
+
+ if (((this.ShowTextMode.Left == 1 && this.Frame.ChartBorder.Top >= 30) || this.ShowTextMode.Left == 2 ||
+ (this.ShowTextMode.Right == 1 && this.Frame.ChartBorder.Bottom >= 30) || this.ShowTextMode.Right == 2) && this.StringFormatY.Operator()) {
+ var text = this.StringFormatY.Text;
+ this.Canvas.font = this.Font;
+ var textWidth = this.Canvas.measureText(text).width + 4; //前后各空2个像素
+
+ if (this.Frame.ChartBorder.Top >= 30 && this.ShowTextMode.Left == 1) {
+ var xText = x, yText = top;
+ this.Canvas.save();
+ this.Canvas.translate(xText, yText);
+ this.Canvas.rotate(90 * Math.PI / 180); //数据和框子旋转180度
+ this.Canvas.fillStyle = this.TextBGColor;
+
+ if (top >= textWidth) {
+ this.Canvas.fillRect(-textWidth, -(this.TextHeight / 2), textWidth, this.TextHeight);
+ this.Canvas.textAlign = "right";
+ this.Canvas.textBaseline = "middle";
+ this.Canvas.fillStyle = this.TextColor;
+ this.Canvas.fillText(text, -2, 0, textWidth);
+ }
+ else {
+ this.Canvas.fillRect((textWidth - top), -(this.TextHeight / 2), -textWidth, this.TextHeight);
+ this.Canvas.textAlign = "right";
+ this.Canvas.textBaseline = "middle";
+ this.Canvas.fillStyle = this.TextColor;
+ this.Canvas.fillText(text, (textWidth - top) - 2, 0, textWidth);
+ }
+ this.Canvas.restore();
+ }
+ else if (this.ShowTextMode.Left == 2) {
+ var xText = x;
+ var yText = top;
+ this.Canvas.save();
+ this.Canvas.translate(xText, yText);
+ this.Canvas.rotate(90 * Math.PI / 180); //数据和框子旋转180度
+
+ this.Canvas.fillStyle = this.TextBGColor;
+ this.Canvas.fillRect(0, -(this.TextHeight / 2), textWidth, this.TextHeight);
+ this.Canvas.textAlign = "left";
+ this.Canvas.textBaseline = "middle";
+ this.Canvas.fillStyle = this.TextColor;
+ this.Canvas.fillText(text, 2, 0, textWidth);
+
+ this.Canvas.restore();
+ }
+
+ if (this.Frame.ChartBorder.Bottom >= 30 && this.ShowTextMode.Right == 1) {
+ var xText = x, yText = bottom;
+ this.Canvas.save();
+ this.Canvas.translate(xText, yText);
+ this.Canvas.rotate(90 * Math.PI / 180); //数据和框子旋转180度
+ this.Canvas.fillStyle = this.TextBGColor;
+
+ if (bottomWidth > textWidth) {
+ this.Canvas.fillRect(0, -(this.TextHeight / 2), textWidth, this.TextHeight);
+ this.Canvas.textAlign = "left";
+ this.Canvas.textBaseline = "middle";
+ this.Canvas.fillStyle = this.TextColor;
+ this.Canvas.fillText(text, 2, 0, textWidth);
+ }
+ else {
+ this.Canvas.fillRect((bottomWidth - textWidth), -(this.TextHeight / 2), textWidth, this.TextHeight);
+ this.Canvas.textAlign = "left";
+ this.Canvas.textBaseline = "middle";
+ this.Canvas.fillStyle = this.TextColor;
+ this.Canvas.fillText(text, (bottomWidth - textWidth) + 2, 0, textWidth);
+ }
+ this.Canvas.restore();
+ }
+ else if (this.ShowTextMode.Right == 2) {
+ var xText = x;
+ var yText = bottom;
+ this.Canvas.save();
+ this.Canvas.translate(xText, yText);
+ this.Canvas.rotate(90 * Math.PI / 180); //数据和框子旋转180度
+
+ this.Canvas.fillStyle = this.TextBGColor;
+ this.Canvas.fillRect(0, -(this.TextHeight / 2), -textWidth, this.TextHeight);
+ this.Canvas.textAlign = "right";
+ this.Canvas.textBaseline = "middle";
+ this.Canvas.fillStyle = this.TextColor;
+ this.Canvas.fillText(text, -2, 0, textWidth);
+
+ this.Canvas.restore();
+ }
+ }
+
+ if (this.ShowTextMode.Bottom === 1 && this.StringFormatX.Operator()) {
+ var text = this.StringFormatX.Text;
+ this.Canvas.font = this.Font;
+
+ this.Canvas.fillStyle = this.TextBGColor;
+ var textWidth = this.Canvas.measureText(text).width + 4; //前后各空2个像素
+ if (y - textWidth / 2 < 3) //左边位置不够了, 顶着左边画
+ {
+ var xText = left;
+ var yText = y;
+ this.Canvas.save();
+ this.Canvas.translate(xText, yText);
+ this.Canvas.rotate(90 * Math.PI / 180); //数据和框子旋转180度
+
+ this.Canvas.fillRect(0, 0, textWidth, this.TextHeight);
+ this.Canvas.textAlign = "center";
+ this.Canvas.textBaseline = "top";
+ this.Canvas.fillStyle = this.TextColor;
+ this.Canvas.fillText(text, 0, 0, textWidth);
+
+ this.Canvas.restore();
+ }
+ else {
+ var xText = left;
+ var yText = y;
+
+ this.Canvas.save();
+ this.Canvas.translate(xText, yText);
+ this.Canvas.rotate(90 * Math.PI / 180); //数据和框子旋转180度
+
+ this.Canvas.fillRect(-(textWidth / 2), 0, textWidth, this.TextHeight);
+ this.Canvas.textAlign = "center";
+ this.Canvas.textBaseline = "top";
+ this.Canvas.fillStyle = this.TextColor;
+ this.Canvas.fillText(text, 0, 0, textWidth);
+
+ this.Canvas.restore();
+ }
+ }
+ }
+}
+
+//分钟线
+function ChartMinutePriceLine()
+{
+ this.newMethod = ChartLine; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.YClose;
+ this.IsDrawArea = true; //是否画价格面积图
+ this.AreaColor = 'rgba(0,191,255,0.1)';
+
+ this.Draw = function ()
+ {
+ if (this.NotSupportMessage)
+ {
+ this.DrawNotSupportmessage();
+ return;
+ }
+
+ if (!this.IsShow) return;
+ if (!this.Data) return;
+
+ var isHScreen = (this.ChartFrame.IsHScreen === true);
+ var dataWidth = this.ChartFrame.DataWidth;
+ var distanceWidth = this.ChartFrame.DistanceWidth;
+ var chartright = this.ChartBorder.GetRight();
+ if (isHScreen === true) chartright = this.ChartBorder.GetBottom();
+ var xPointCount = this.ChartFrame.XPointCount;
+ var minuteCount = this.ChartFrame.MinuteCount;
+ var bottom = this.ChartBorder.GetBottomEx();
+ var left = this.ChartBorder.GetLeftEx();
+
+ var bFirstPoint = true;
+ var ptFirst = {}; //第1个点
+ var drawCount = 0;
+ for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j)
+ {
+ var value = this.Data.Data[i];
+ if (value == null) continue;
+
+ var x = this.ChartFrame.GetXFromIndex(j);
+ var y = this.ChartFrame.GetYFromData(value);
+
+ if (bFirstPoint)
+ {
+ this.Canvas.strokeStyle = this.Color;
+ this.Canvas.beginPath();
+ if (isHScreen) this.Canvas.moveTo(y, x);
+ else this.Canvas.moveTo(x, y);
+ bFirstPoint = false;
+ ptFirst = { X: x, Y: y };
+ }
+ else
+ {
+ if (isHScreen) this.Canvas.lineTo(y, x);
+ else this.Canvas.lineTo(x, y);
+ }
+
+ ++drawCount;
+
+ if (drawCount >= minuteCount) //上一天的数据和这天地数据线段要断开
+ {
+ bFirstPoint = true;
+ this.Canvas.stroke();
+ if (this.IsDrawArea) //画面积
+ {
+ if (isHScreen)
+ {
+ this.Canvas.lineTo(left, x);
+ this.Canvas.lineTo(left, ptFirst.X);
+ this.SetFillStyle(this.AreaColor, this.ChartBorder.GetRightEx(), bottom, this.ChartBorder.GetLeftEx(), bottom);
+ }
+ else
+ {
+ this.Canvas.lineTo(x, bottom);
+ this.Canvas.lineTo(ptFirst.X, bottom);
+ this.SetFillStyle(this.AreaColor, left, this.ChartBorder.GetTopEx(), left, bottom);
+ }
+ this.Canvas.fill();
+ }
+ drawCount = 0;
+ }
+ }
+
+ if (drawCount > 0)
+ {
+ this.Canvas.stroke();
+ if (this.IsDrawArea) //画面积
+ {
+ if (isHScreen)
+ {
+ this.Canvas.lineTo(left, x);
+ this.Canvas.lineTo(left, ptFirst.X);
+ this.SetFillStyle(this.AreaColor, this.ChartBorder.GetRightEx(), bottom, this.ChartBorder.GetLeftEx(), bottom);
+ }
+ else
+ {
+ this.Canvas.lineTo(x, bottom);
+ this.Canvas.lineTo(ptFirst.X, bottom);
+ this.SetFillStyle(this.AreaColor, left, this.ChartBorder.GetTopEx(), left, bottom);
+ }
+ this.Canvas.fill();
+ }
+ }
+ }
+
+ this.GetMaxMin = function ()
+ {
+ var xPointCount = this.ChartFrame.XPointCount;
+ var range = {};
+ if (this.YClose == null) return range;
+
+ range.Min = this.YClose;
+ range.Max = this.YClose;
+ for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j)
+ {
+ var value = this.Data.Data[i];
+ if (!value) continue;
+
+ if (range.Max == null) range.Max = value;
+ if (range.Min == null) range.Min = value;
+
+ if (range.Max < value) range.Max = value;
+ if (range.Min > value) range.Min = value;
+ }
+
+ if (range.Max == this.YClose && range.Min == this.YClose)
+ {
+ range.Max = this.YClose + this.YClose * 0.1;
+ range.Min = this.YClose - this.YClose * 0.1;
+ return range;
+ }
+
+ var distance = Math.max(Math.abs(this.YClose - range.Max), Math.abs(this.YClose - range.Min));
+ range.Max = this.YClose + distance;
+ range.Min = this.YClose - distance;
+
+ return range;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//深度图十字光标
+function DepthChartCorssCursor()
+{
+ this.Frame;
+ this.Canvas; //画布
+ this.Data;
+ this.Symbol;
+ this.HQChart;
+
+ this.HPenType=0; //水平线样式 0=虚线 1=实线
+ this.VPenType=0; //垂直线颜色 0=虚线 1=实线
+ this.LineDash=g_JSChartResource.DepthCorss.LineDash;
+
+ this.AskColor=g_JSChartResource.DepthCorss.AskColor.Line; //卖
+ this.BidColor=g_JSChartResource.DepthCorss.BidColor.Line; //买
+ this.LineWidth=g_JSChartResource.DepthCorss.LineWidth;
+
+ this.IsShowTooltip=true;
+ this.Tooltip=
+ {
+ LineHeight:g_JSChartResource.DepthCorss.Tooltip.LineHeight,
+ Border:
+ {
+ Top:g_JSChartResource.DepthCorss.Tooltip.Border.Top,
+ Left:g_JSChartResource.DepthCorss.Tooltip.Border.Left,
+ Bottom:g_JSChartResource.DepthCorss.Tooltip.Border.Bottom,
+ Center: g_JSChartResource.DepthCorss.Tooltip.Border.Center
+ },
+ Font:g_JSChartResource.DepthCorss.Tooltip.Font,
+ TextColor:g_JSChartResource.DepthCorss.Tooltip.TextColor,
+ BGColor:g_JSChartResource.DepthCorss.Tooltip.BGColor
+ }; // Width: Height:
+
+ this.Font=g_JSChartResource.CorssCursorTextFont; //字体
+ this.TextColor=g_JSChartResource.CorssCursorTextColor; //文本颜色
+ this.TextBGColor=g_JSChartResource.CorssCursorBGColor; //文本背景色
+ this.TextHeight=20; //文本字体高度
+ this.LastPoint;
+
+ this.PointX;
+ this.PointY;
+
+ this.StringFormatX;
+ this.StringFormatY;
+
+ this.IsShowCorss=true; //是否显示十字光标
+ this.IsShow=true;
+
+ this.GetVol=function(price, isAsk)
+ {
+ if (!this.Data) return null;
+ var aryData=isAsk? this.Data.Asks:this.Data.Bids;
+ if (!aryData || !Array.isArray(aryData) || aryData.length<=0) return null;
+
+ for(var i in aryData)
+ {
+ var item=aryData[i];
+ if (item.Price==price) return item.Vol;
+ }
+
+ return null;
+ }
+
+ this.Draw=function()
+ {
+ this.Status=0;
+ if (!this.LastPoint) return;
+ if (!this.Data) return;
+ if (!this.IsShow) return;
+
+ var x=this.LastPoint.X;
+ var y=this.LastPoint.Y;
+
+ var isInClient=false;
+ var rtClient = new Rect(this.Frame.ChartBorder.GetLeft(), this.Frame.ChartBorder.GetTop(), this.Frame.ChartBorder.GetWidth(), this.Frame.ChartBorder.GetHeight());
+ isInClient = rtClient.IsPointIn(x, y);
+
+ this.PointY=null;
+ this.PointY==null;
+
+ if (!isInClient) return;
+
+ if (this.Frame.IsHScreen===true)
+ {
+ return;
+ }
+
+ var left=this.Frame.ChartBorder.GetLeft();
+ var right=this.Frame.ChartBorder.GetRight();
+ var top=this.Frame.ChartBorder.GetTopTitle();
+ var bottom=this.Frame.ChartBorder.GetBottom();
+ var rightWidth=this.Frame.ChartBorder.Right;
+ var chartRight=this.Frame.ChartBorder.GetChartWidth();
+
+ var xValue=this.Frame.GetXData(x);
+ var xInfo=this.Frame.GetXFromPrice(xValue); //调整价格到有数据的点上
+
+ if (!xInfo) return;
+
+ var yVol=this.GetVol(xInfo.Price, xInfo.IsAsk);
+ y=this.Frame.GetYFromData(yVol); //调整Y轴, 让它在线段上
+
+ xInfo.Vol=yVol;
+ xInfo.Y=y;
+
+ this.PointY=[[left,y],[right,y]];
+ this.PointX=[[x,top],[x,bottom]];
+
+ if (this.IsShowCorss)
+ {
+ if (xInfo.IsAsk) this.Canvas.strokeStyle=this.AskColor;
+ else this.Canvas.strokeStyle=this.BidColor;
+ this.Canvas.save();
+ this.Canvas.lineWidth=this.LineWidth;
+ var lineWidth=this.Canvas.lineWidth;
+
+ if (this.HPenType==1 || this.HPenType==0) //0=实线 1=虚线
+ {
+ if (this.HPenType==0) this.Canvas.setLineDash(this.LineDash); //虚线
+ var yFix=ToFixedPoint(y);
+ this.Canvas.beginPath();
+ this.Canvas.moveTo(left,yFix);
+ this.Canvas.lineTo(right,yFix);
+ this.Canvas.stroke();
+ if (this.HPenType==0) this.Canvas.setLineDash([]);
+ }
+
+ if (this.VPenType==0) this.Canvas.setLineDash(this.LineDash); //虚线
+ var xFix=ToFixedPoint(xInfo.X);
+ this.Canvas.beginPath();
+ this.Canvas.moveTo(xFix,top);
+ this.Canvas.lineTo(xFix,bottom);
+ this.Canvas.stroke();
+ if (this.VPenType==0) this.Canvas.setLineDash([]);
+
+ this.Canvas.restore();
+ }
+
+ if (this.HQChart)
+ {
+ //JSCHART_EVENT_ID.ON_DRAW_DEPTH_TOOLTIP
+ var event=this.HQChart.GetEvent(25);
+ if (event)
+ {
+ event.Callback(event,xInfo,this);
+ }
+ }
+
+ if (this.IsShowTooltip) this.DrawTooltip(xInfo);
+ }
+
+ this.DrawTooltip=function(data)
+ {
+ var price=data.Price;
+ var vol=data.Vol;
+ var border=this.Tooltip.Border;
+ this.Canvas.font=this.Tooltip.Font;
+ var floatPrecision=2;
+ if (this.Symbol) floatPrecision=JSCommonCoordinateData.GetfloatPrecision(this.Symbol);//价格小数位数
+ var maxText='擎擎: 9999.99亿 ';
+ if (floatPrecision>=5) maxText=`擎擎: ${99.99.toFixed(floatPrecision)} `; //小数位数太多了
+ this.Tooltip.Width=this.Canvas.measureText(maxText).width+border.Left;
+ this.Tooltip.Height=this.Tooltip.LineHeight*4+border.Top+border.Bottom+border.Center;
+
+ var chartRight=this.Frame.ChartBorder.GetRight();
+ var chartTop=this.Frame.ChartBorder.GetTop();
+
+ var left=data.X+2;
+ var top=data.Y-this.Tooltip.Height-2;
+ if (left+this.Tooltip.Width>=chartRight) left=data.X-this.Tooltip.Width-2;
+ if (topxRange.Max) break;
+ }
+
+ var x=this.ChartFrame.GetXFromIndex(item.Price);
+ var y=this.ChartFrame.GetYFromData(item.Vol);
+ aryPoint.push({X:x,Y:y});
+ }
+ if (aryPoint.length<=1) return;
+
+ var left=this.ChartBorder.GetLeft();
+ var bottom=this.ChartBorder.GetBottom();
+ var right=this.ChartBorder.GetRight();
+
+ this.Canvas.beginPath();
+ this.Canvas.moveTo(aryPoint[0].X, bottom);
+ for(var i in aryPoint)
+ {
+ var item=aryPoint[i];
+ this.Canvas.lineTo(item.X,item.Y);
+ }
+
+ this.Canvas.lineTo(isLeft?left:right,aryPoint[aryPoint.length-1].Y);
+ this.Canvas.lineTo(isLeft?left:right,bottom);
+ this.Canvas.lineTo(aryPoint[0].X,bottom);
+ this.Canvas.closePath();
+ this.Canvas.fillStyle = colorArea;
+ this.Canvas.fill();
+
+ this.Canvas.beginPath();
+ this.Canvas.moveTo(aryPoint[0].X, bottom);
+ for(var i in aryPoint)
+ {
+ var item=aryPoint[i];
+ this.Canvas.lineTo(item.X,item.Y);
+ }
+ this.Canvas.lineTo(isLeft?left:right,aryPoint[aryPoint.length-1].Y);
+ this.Canvas.strokeStyle=colorLine;
+ this.Canvas.stroke();
+ }
+
+ this.GetMaxMin=function()
+ {
+ var range={ Min:null, Max:null, XMin:null, XMax:null };
+ var xRange=this.ChartFrame.VerticalRange;
+
+ for(var i in this.Data.Asks)
+ {
+ var item=this.Data.Asks[i];
+ if (item.Price>xRange.Max) break;
+
+ if (range.XMin==null || range.XMin>item.Price) range.XMin=item.Price;
+ if (range.XMax==null || range.XMaxitem.Vol) range.Min=item.Vol;
+ if (range.Max==null || range.Maxitem.Price) range.XMin=item.Price;
+ if (range.XMax==null || range.XMaxitem.Vol) range.Min=item.Vol;
+ if (range.Max==null || range.Max= this.Data.Data.length) dataIndex = this.Data.Data.length - 1;
+ if (dataIndex < 0) return null;
+
+ var item = this.Data.Data[dataIndex];
+ return item;
+ }
+
+ this.GetDataIndex=function()
+ {
+ if (this.CursorIndex == null || !this.Data) return null;
+ if (this.Data.length <= 0) return null;
+
+ var index = this.CursorIndex;
+ index = parseInt(index.toFixed(0));
+ var dataIndex = this.Data.DataOffset + index;
+ if (dataIndex >= this.Data.Data.length) dataIndex = this.Data.Data.length - 1;
+ if (dataIndex < 0) return null;
+
+ return dataIndex;
+ }
+
+ this.SendUpdateUIMessage = function (funcName) //通知外面 标题变了
+ {
+ if (!this.UpdateUICallback) return;
+
+ var sendData = {
+ TitleName: 'K线标题', CallFunction: funcName, Stock: { Name: this.Name, Symbol: this.Symbol, },
+ Rect:
+ {
+ Left: this.Frame.ChartBorder.GetLeft(), Right: this.Frame.ChartBorder.GetRight(),
+ Top: 0, Bottom: this.Frame.ChartBorder.GetTop(),
+ }
+ };
+
+ //有数据
+ if (this.Data && this.Data.Data && this.Data.Data.length > 0) {
+ let index = this.Data.Data.length - 1; //默认最后一天的数据
+ if (this.CursorIndex) {
+ let cursorIndex = Math.abs(this.CursorIndex - 0.5);
+ cursorIndex = parseInt(cursorIndex.toFixed(0));
+ index = this.Data.DataOffset + cursorIndex;
+ if (index >= this.Data.Data.length) index = this.Data.Data.length - 1;
+ }
+
+ if (index >= 0) {
+ let item = this.Data.Data[index];
+ sendData.Stock.Data =
+ {
+ Date: item.Date,
+ YClose: item.YClose, Open: item.Open, High: item.High, Low: item.Low, Close: item.Close,
+ Vol: item.Vol, Amount: item.Amount
+ }
+ if (item.Time) sendData.Stock.Time = item.Time; //分钟K线才有时间
+ }
+
+ if (this.Data.Period != null) sendData.Stock.PeriodName = this.GetPeriodName(this.Data.Period); //周期名字
+ if (this.Data.Right != null) sendData.Stock.RightName = RIGHT_NAME[this.Data.Right]; //复权名字
+ }
+
+ //console.log('[DynamicKLineTitlePainting::SendUpdateUIMessage', sendData);
+ this.UpdateUICallback(sendData);
+ }
+
+ this.GetPeriodName = function (period)
+ {
+ var name = '';
+ if (period > CUSTOM_MINUTE_PERIOD_START && period <= CUSTOM_MINUTE_PERIOD_END)
+ name = (period - CUSTOM_MINUTE_PERIOD_START) + g_JSChartLocalization.GetText('自定义分钟', this.LanguageID);
+ else if (period > CUSTOM_DAY_PERIOD_START && period <= CUSTOM_DAY_PERIOD_END)
+ name = (period - CUSTOM_DAY_PERIOD_START) + g_JSChartLocalization.GetText('自定义日线',this.LanguageID);
+ else if (period > CUSTOM_SECOND_PERIOD_START && period <= CUSTOM_SECOND_PERIOD_END)
+ name = (period - CUSTOM_SECOND_PERIOD_START) + g_JSChartLocalization.GetText('自定义秒', this.LanguageID);
+ else
+ name = g_JSChartLocalization.GetText(ChartData.GetPeriodName(period), this.LanguageID);
+ return name;
+ }
+
+ this.GetRightName = function (rightID, periodID)
+ {
+ //分钟K线没有复权
+ if (ChartData.IsMinutePeriod(periodID, true) || ChartData.IsSecondPeriod(periodID))
+ return null;
+
+ if (MARKET_SUFFIX_NAME.IsSHSZStockA(this.UpperSymbol)) //A股有复权
+ {
+ var rightName = RIGHT_NAME[rightID];
+ return rightName
+ }
+
+ return null;
+ }
+
+ this.FullDraw=function()
+ {
+ if (!this.IsShow) return;
+ this.UpperSymbol=this.Symbol ? this.Symbol.toUpperCase():'';
+ if (this.CursorIndex == null || !this.Data || this.Data.length <= 0)
+ {
+ this.OnDrawEventCallback(null, 'DynamicKLineTitlePainting::FullDraw');
+ return;
+ }
+
+ this.SpaceWidth = this.Canvas.measureText(' ').width;
+ var index = this.CursorIndex;
+ index = parseInt(index.toFixed(0));
+ var dataIndex = this.Data.DataOffset + index;
+ if (dataIndex >= this.Data.Data.length) dataIndex=-1;
+ if (dataIndex < 0)
+ {
+ this.OnDrawEventCallback(null, 'DynamicKLineTitlePainting::FullDraw');
+ return;
+ }
+
+ var item = this.Data.Data[dataIndex];
+ this.OnDrawEventCallback(item, 'DynamicKLineTitlePainting::FullDraw');
+
+ if (this.Frame.IsHScreen === true)
+ {
+ this.Canvas.save();
+ if (this.LineCount > 1) this.DrawMulitLine(item);
+ else this.DrawSingleLine(item,true);
+ this.Canvas.restore();
+ if (!item.Time && item.Date && this.InfoData) this.HSCreenKLineInfoDraw(item.Date);
+ }
+ else
+ {
+ if (this.LineCount > 1) this.DrawMulitLine(item);
+ else this.DrawSingleLine(item, true);
+ if (!item.Time && item.Date && this.InfoData) this.KLineInfoDraw(item.Date);
+ }
+ }
+
+ this.DrawTitle = function ()
+ {
+ this.UpperSymbol=this.Symbol ? this.Symbol.toUpperCase():'';
+ this.SendUpdateUIMessage('DrawTitle');
+ this.OnDrawEventCallback(null, 'DynamicKLineTitlePainting::DrawTitle');
+
+ if (!this.IsShow) return;
+ if (!this.IsShowName && !this.IsShowSettingInfo) return;
+ if (this.LineCount > 1) return;
+
+ if (this.Frame.IsHScreen === true)
+ {
+ this.Canvas.save();
+ this.HScreenDrawTitle();
+ this.Canvas.restore();
+ return;
+ }
+
+ var left = this.Frame.ChartBorder.GetLeft();
+ var bottom = this.Frame.ChartBorder.GetTop();
+ var right = this.Frame.ChartBorder.GetRight();
+ if (bottom < 5) return;
+
+ this.Canvas.textAlign = "left";
+ this.Canvas.textBaseline = "bottom";
+ this.Canvas.font = this.Font;
+ var position = { Left: left, Bottom: bottom, IsHScreen: false };
+
+ if (this.IsShowName && this.Name)
+ {
+ if (!this.DrawKLineText(this.Name, this.NameColor, position)) return;
+ }
+
+ if (this.IsShowSettingInfo && this.Data.Period != null && this.Data.Right != null)
+ {
+ var periodName = this.GetPeriodName(this.Data.Period);
+ var rightName = this.GetRightName(this.Data.Right,this.Data.Period);
+ var text = "(" + periodName + ")";
+ if (rightName) text = "(" + periodName + " " + rightName + ")";
+ if (!this.DrawKLineText(text, this.SettingColor, position)) return;
+ }
+ }
+
+ this.HScreenDrawTitle = function ()
+ {
+ var xText = this.Frame.ChartBorder.GetRight();
+ var yText = this.Frame.ChartBorder.GetTop();
+ var right = this.Frame.ChartBorder.GetHeight();
+ if (this.Frame.ChartBorder.Right < 10) return;
+
+ this.Canvas.translate(xText, yText);
+ this.Canvas.rotate(90 * Math.PI / 180);
+
+ this.Canvas.textAlign = "left";
+ this.Canvas.textBaseline = "bottom";
+ this.Canvas.font = this.Font;
+
+ var left = 2;
+ var bottom = -2;
+ var position = { Left: left, Bottom: bottom, IsHScreen: false };
+ if (this.IsShowName && this.Name)
+ {
+ if (!this.DrawKLineText(this.Name, this.NameColor, position)) return;
+ }
+
+ if (this.IsShowSettingInfo && this.Data.Period != null && this.Data.Right != null)
+ {
+ var periodName = this.GetPeriodName(this.Data.Period);
+ var rightName = this.GetRightName(this.Data.Right,this.Data.Period);
+ var text = "(" + periodName + ")";
+ if (rightName) text = "(" + periodName + " " + rightName + ")";
+ if (!this.DrawKLineText(text, this.SettingColor, position)) return;
+ }
+ }
+
+ this.DrawMulitLine = function (item) //画多行
+ {
+ var isHScreen = this.Frame.IsHScreen === true;
+ var leftSpace = 1;
+ var bottomSpace = 1;
+ var left = this.Frame.ChartBorder.GetLeft() + leftSpace;;
+ var width = this.Frame.ChartBorder.GetWidth();
+ var height = this.Frame.ChartBorder.GetTop();
+ var defaultfloatPrecision = JSCommonCoordinateData.GetfloatPrecision(this.Symbol);//价格小数位数
+ if (isHScreen)
+ {
+ var left = leftSpace;;
+ var width = this.Frame.ChartBorder.GetHeight();
+ var height = this.Frame.ChartBorder.Right;
+ var xText = this.Frame.ChartBorder.GetChartWidth();
+ var yText = this.Frame.ChartBorder.GetTop();
+
+ this.Canvas.translate(xText, yText);
+ this.Canvas.rotate(90 * Math.PI / 180);
+ }
+
+ var itemHeight = (height - bottomSpace) / this.LineCount;
+ var itemWidth = (width - leftSpace) / 4;
+ var bottom = itemHeight;
+
+ this.Canvas.textAlign = "left";
+ this.Canvas.textBaseline = "bottom";
+ this.Canvas.font = this.Font;
+
+ var text = IFrameSplitOperator.FormatDateString(item.Date);
+ this.Canvas.fillStyle = this.DateTimeColor;
+ this.Canvas.fillText(text, left, bottom, itemWidth);
+ left += itemWidth;
+
+ this.Canvas.textAlign = "left";
+ this.Canvas.fillStyle = this.GetColor(item.Open, item.YClose);
+ var text = g_JSChartLocalization.GetText('Tooltip-Open', this.LanguageID) + item.Open.toFixed(defaultfloatPrecision);
+ this.Canvas.fillText(text, left, bottom, itemWidth);
+ left += itemWidth;
+
+ this.Canvas.fillStyle = this.GetColor(item.High, item.YClose);
+ var text = g_JSChartLocalization.GetText('Tooltip-High', this.LanguageID) + item.High.toFixed(defaultfloatPrecision);
+ this.Canvas.fillText(text, left, bottom, itemWidth);
+ left += itemWidth;
+
+ var value = (item.Close - item.YClose) / item.YClose * 100;
+ this.Canvas.fillStyle = this.GetColor(value, 0);
+ var text = g_JSChartLocalization.GetText('Tooltip-Increase', this.LanguageID) + value.toFixed(2) + '%';
+ this.Canvas.fillText(text, left, bottom, itemWidth);
+ left += itemWidth;
+
+ bottom += itemHeight; //换行
+ var left = this.Frame.ChartBorder.GetLeft() + leftSpace;
+ if (isHScreen) left = leftSpace;
+ if (ChartData.IsMinutePeriod(this.Period, true) && item.Time)
+ {
+ this.Canvas.fillStyle = this.DateTimeColor;
+ var text = IFrameSplitOperator.FormatTimeString(item.Time);
+ this.Canvas.fillText(text, left, bottom, itemWidth);
+ }
+ else if (ChartData.IsSecondPeriod(this.Period) && item.Time)
+ {
+ this.Canvas.fillStyle = this.SettingColor;
+ var text = IFrameSplitOperator.FormatTimeString(item.Time, 'HH:MM:SS');
+ this.Canvas.fillText(text, left, bottom, itemWidth);
+ }
+ left += itemWidth;
+
+ this.Canvas.fillStyle = this.GetColor(item.Close, item.YClose);
+ var text = g_JSChartLocalization.GetText('Tooltip-Close', this.LanguageID) + item.Close.toFixed(defaultfloatPrecision);
+ this.Canvas.fillText(text, left, bottom, itemWidth);
+ left += itemWidth;
+
+ this.Canvas.fillStyle = this.GetColor(item.Low, item.YClose);
+ var text = g_JSChartLocalization.GetText('Tooltip-Low', this.LanguageID) + item.Low.toFixed(defaultfloatPrecision);
+ this.Canvas.fillText(text, left, bottom, itemWidth);
+ left += itemWidth;
+
+ this.Canvas.fillStyle = this.AmountColor;
+ var text = g_JSChartLocalization.GetText('Tooltip-Amount', this.LanguageID) + IFrameSplitOperator.FormatValueString(item.Amount, 2, this.LanguageID);
+ this.Canvas.fillText(text, left, bottom, itemWidth);
+ left += itemWidth;
+ }
+
+ this.DrawSingleLine = function (item,bDrawTitle) //画单行
+ {
+ var isHScreen = this.Frame.IsHScreen === true;
+ var left = this.Frame.ChartBorder.GetLeft();
+ //var bottom=this.Frame.ChartBorder.GetTop()-this.Frame.ChartBorder.Top/2;
+ var bottom = this.Frame.ChartBorder.GetTop();
+ var right = this.Frame.ChartBorder.GetRight();
+ var defaultfloatPrecision = JSCommonCoordinateData.GetfloatPrecision(this.Symbol);//价格小数位数
+
+ if (isHScreen)
+ {
+ right = this.Frame.ChartBorder.GetHeight();
+ if (this.Frame.ChartBorder.Right < 5) return;
+ left = 2;
+ bottom = -2;
+ var xText = this.Frame.ChartBorder.GetRight();
+ var yText = this.Frame.ChartBorder.GetTop();
+ this.Canvas.translate(xText, yText);
+ this.Canvas.rotate(90 * Math.PI / 180);
+ }
+ else
+ {
+ if (bottom < 5) return;
+ }
+
+ this.Canvas.textAlign = "left";
+ this.Canvas.textBaseline = "bottom";
+ this.Canvas.font = this.Font;
+
+ var position = { Left: left, Bottom: bottom, IsHScreen: isHScreen };
+
+ if (this.IsShowName) //名称
+ {
+ if (!this.DrawKLineText(this.Name, this.NameColor, position, bDrawTitle==true)) return;
+ }
+
+ if (this.IsShowSettingInfo) //周期 复权信息
+ {
+ var periodName = this.GetPeriodName(this.Data.Period);
+ var rightName = this.GetRightName(this.Data.Right,this.Data.Period);
+ var text = "(" + periodName + ")";
+ if (rightName) text = "(" + periodName + " " + rightName + ")";
+ if (!this.DrawKLineText(text, this.SettingColor, position, bDrawTitle==true)) return;
+ }
+
+ var text = IFrameSplitOperator.FormatDateString(item.Date); //日期
+ if (!this.DrawKLineText(text, this.DateTimeColor, position)) return;
+
+ //时间
+ if (ChartData.IsMinutePeriod(this.Period, true) && IFrameSplitOperator.IsNumber(item.Time))
+ {
+ var text = IFrameSplitOperator.FormatTimeString(item.Time);
+ if (!this.DrawKLineText(text, this.DateTimeColor, position)) return;
+ }
+ else if (ChartData.IsSecondPeriod(this.Period) && IFrameSplitOperator.IsNumber(item.Time))
+ {
+ var text = IFrameSplitOperator.FormatTimeString(item.Time, "HH:MM:SS");
+ if (!this.DrawKLineText(text, this.DateTimeColor, position)) return;
+ }
+
+ var color = this.GetColor(item.Open, item.YClose);
+ var text = g_JSChartLocalization.GetText('KTitle-Open', this.LanguageID) + item.Open.toFixed(defaultfloatPrecision);
+ if (!this.DrawKLineText(text, color, position)) return;
+
+ var color = this.GetColor(item.High, item.YClose);
+ var text = g_JSChartLocalization.GetText('KTitle-High', this.LanguageID) + item.High.toFixed(defaultfloatPrecision);
+ if (!this.DrawKLineText(text, color, position)) return;
+
+ var color = this.GetColor(item.Low, item.YClose);
+ var text = g_JSChartLocalization.GetText('KTitle-Low', this.LanguageID) + item.Low.toFixed(defaultfloatPrecision);
+ if (!this.DrawKLineText(text, color, position)) return;
+
+ var color = this.GetColor(item.Close, item.YClose);
+ var text = g_JSChartLocalization.GetText('KTitle-Close', this.LanguageID) + item.Close.toFixed(defaultfloatPrecision);
+ if (!this.DrawKLineText(text, color, position)) return;
+
+ if (IFrameSplitOperator.IsNumber(item.Vol))
+ {
+ var text = g_JSChartLocalization.GetText('KTitle-Vol', this.LanguageID) + IFrameSplitOperator.FormatValueString(item.Vol, 2);
+ if (!this.DrawKLineText(text, this.VolColor, position)) return;
+ }
+
+ if (IFrameSplitOperator.IsNumber(item.Amount))
+ {
+ var text = g_JSChartLocalization.GetText('KTitle-Amount', this.LanguageID) + IFrameSplitOperator.FormatValueString(item.Amount, 2);
+ if (!this.DrawKLineText(text, this.AmountColor, position)) return;
+ }
+
+ if (MARKET_SUFFIX_NAME.IsChinaFutures(this.UpperSymbol) && IFrameSplitOperator.IsNumber(item.Position))
+ {
+ var text = g_JSChartLocalization.GetText('KTitle-Position', this.LanguageID) + IFrameSplitOperator.FormatValueString(item.Position, 2);
+ if (!this.DrawKLineText(text, this.PositionColor, position)) return;
+ }
+ }
+
+ this.OnDrawEventCallback = function (drawData, explain)
+ {
+ if (!this.OnDrawEvent || !this.OnDrawEvent.Callback) return;
+ var data = { Draw: drawData, Name: this.ClassName, Explain: explain };
+ if (this.Data && this.Data.Data)
+ {
+ if (IFrameSplitOperator.IsNumber(this.CursorIndex))
+ {
+ var index = this.CursorIndex;
+ index = parseInt(index.toFixed(0));
+ var dataIndex = this.Data.DataOffset + index;
+ }
+ else
+ {
+ dataIndex=this.Data.Data.length-1;
+ }
+
+ var dataCount=this.Data.Data.length;
+ data.DataIndex=dataIndex;
+ data.DataCount=dataCount;
+ }
+ this.OnDrawEvent.Callback(this.OnDrawEvent, data, this);
+ }
+
+ this.Draw = function ()
+ {
+ this.UpperSymbol = this.Symbol ? this.Symbol.toUpperCase() : '';
+ this.SendUpdateUIMessage('Draw');
+
+ if (!this.IsShow) return;
+ if (this.CursorIndex == null || !this.Data || this.Data.length <= 0)
+ {
+ this.OnDrawEventCallback(null, 'DynamicKLineTitlePainting::Draw');
+ return;
+ }
+
+ this.SpaceWidth = this.Canvas.measureText(' ').width;
+ var index = this.CursorIndex;
+ index = parseInt(index.toFixed(0));
+ var dataIndex = this.Data.DataOffset + index;
+ if (dataIndex >= this.Data.Data.length) dataIndex = this.Data.Data.length - 1;
+ if (dataIndex < 0)
+ {
+ this.OnDrawEventCallback(null, 'DynamicKLineTitlePainting::Draw');
+ return;
+ }
+
+ var item = this.Data.Data[dataIndex];
+ this.OnDrawEventCallback(item, 'DynamicKLineTitlePainting::Draw');
+
+ if (this.Frame.IsHScreen === true)
+ {
+ this.Canvas.save();
+ if (this.LineCount > 1) this.DrawMulitLine(item);
+ else this.DrawSingleLine(item);
+ this.Canvas.restore();
+ if (!item.Time && item.Date && this.InfoData) this.HSCreenKLineInfoDraw(item.Date);
+ }
+ else
+ {
+ if (this.LineCount > 1) this.DrawMulitLine(item);
+ else this.DrawSingleLine(item);
+
+ if (!item.Time && item.Date && this.InfoData) this.KLineInfoDraw(item.Date);
+ }
+ }
+
+
+ this.KLineInfoDraw = function (date) {
+ var info = this.InfoData.get(date.toString());
+ if (!info) return;
+ var invesotrCount = 0; //互动易统计
+ var researchCouunt = 0;
+ var reportCount = 0;
+ var blockTradeCount = 0; //大宗交易次数
+ var tradeDetailCount = 0; //龙虎榜上榜次数
+ var policyData = null;
+ var reportTitle = null, pforecastTitle = null;
+ //console.log(info);
+ for (var i in info.Data) {
+ var item = info.Data[i];
+ switch (item.InfoType) {
+ case KLINE_INFO_TYPE.INVESTOR:
+ ++invesotrCount;
+ break;
+ case KLINE_INFO_TYPE.PFORECAST:
+ pforecastTitle = item.Title;
+ break;
+ case KLINE_INFO_TYPE.ANNOUNCEMENT:
+ ++reportCount;
+ break;
+ case KLINE_INFO_TYPE.ANNOUNCEMENT_QUARTER_1:
+ case KLINE_INFO_TYPE.ANNOUNCEMENT_QUARTER_2:
+ case KLINE_INFO_TYPE.ANNOUNCEMENT_QUARTER_3:
+ case KLINE_INFO_TYPE.ANNOUNCEMENT_QUARTER_4:
+ reportTitle = item.Title;
+ break;
+ case KLINE_INFO_TYPE.RESEARCH:
+ ++researchCouunt;
+ break;
+ case KLINE_INFO_TYPE.BLOCKTRADING:
+ ++blockTradeCount;
+ break;
+ case KLINE_INFO_TYPE.TRADEDETAIL:
+ ++tradeDetailCount;
+ break;
+ case KLINE_INFO_TYPE.POLICY:
+ policyData = item;
+ break;
+ }
+ }
+
+ var isHScreen = (this.Frame.IsHScreen === true);
+ var right = this.Frame.ChartBorder.GetRight() - 4;
+ var top = this.Frame.ChartBorder.GetTopEx();
+ if (isHScreen) {
+ right = this.Frame.ChartBorder.GetBottom() - 4;
+ top = this.Frame.ChartBorder.GetRightEx();
+ this.Canvas.translate(top, right);
+ this.Canvas.rotate(90 * Math.PI / 180);
+ right = 0; top = 0;
+ }
+
+ this.Canvas.font = this.Font;
+
+ var aryTitle = [];
+ var position = { Top: top, Right: right, IsHScreen: isHScreen };
+
+ aryTitle.push(IFrameSplitOperator.FormatDateString(date));
+ if (reportTitle) aryTitle.push(reportTitle); //季报
+ if (pforecastTitle) aryTitle.push(pforecastTitle); //业绩预告
+ if (reportCount > 0) aryTitle.push('公告数量:' + reportCount);
+ if (researchCouunt > 0) aryTitle.push('机构调研次数:' + researchCouunt);
+ if (tradeDetailCount > 0) aryTitle.push('龙虎榜上榜次数:' + tradeDetailCount);
+ if (invesotrCount > 0) aryTitle.push('互动易数量:' + invesotrCount);
+ if (blockTradeCount > 0) aryTitle.push('大宗交易次数:' + blockTradeCount);
+ if (policyData) //策略选股
+ {
+ for (let i in policyData.ExtendData) //显示满足的策略
+ {
+ aryTitle.push(policyData.ExtendData[i].Name);
+ }
+ }
+
+ var maxWidth = 0, textBGHeight = 0;
+ for (let i in aryTitle) {
+ var item = aryTitle[i];
+ var textWidth = this.Canvas.measureText(item).width + 2; //后空2个像素
+ if (maxWidth < textWidth) maxWidth = textWidth;
+ textBGHeight += this.InfoTextHeight;
+ }
+
+ this.Canvas.fillStyle = this.InfoTextBGColor;
+ if (isHScreen) this.Canvas.fillRect(position.Right - maxWidth, position.Top, maxWidth + 2, textBGHeight + 2);
+ else this.Canvas.fillRect(position.Right - maxWidth, position.Top, maxWidth + 2, textBGHeight + 2);
+
+ for (let i in aryTitle) {
+ var item = aryTitle[i];
+ this.DrawInfoText(item, position);
+ }
+ }
+
+ this.HSCreenKLineInfoDraw = function (date) {
+ this.Canvas.save();
+ this.KLineInfoDraw(date);
+ this.Canvas.restore();
+ }
+
+ this.GetColor = function (price, yclse) {
+ if (price > yclse) return this.UpColor;
+ else if (price < yclse) return this.DownColor;
+ else return this.UnchagneColor;
+ }
+
+ this.DrawInfoText = function (title, position) {
+ if (!title) return true;
+
+ this.Canvas.textAlign = "right";
+ this.Canvas.textBaseline = "top";
+ this.Canvas.fillStyle = this.InfoTextColor;
+ this.Canvas.fillText(title, position.Right, position.Top);
+ position.Top += this.InfoTextHeight;
+ return true;
+ }
+
+ this.DrawKLineText = function (title, color, position, isShow)
+ {
+ if (!title) return true;
+
+ var isHScreen = this.Frame.IsHScreen === true;
+ var right = this.Frame.ChartBorder.GetRight();
+ if (isHScreen) right = this.Frame.ChartBorder.GetHeight();
+
+ this.Canvas.fillStyle = color;
+ var textWidth = this.Canvas.measureText(title).width;
+ if (position.Left + textWidth > right) return false;
+ if (!(isShow === false)) this.Canvas.fillText(title, position.Left, position.Bottom, textWidth);
+
+ position.Left += textWidth + this.SpaceWidth;
+ return true;
+ }
+
+}
+
+//分时图标题
+function DynamicMinuteTitlePainting()
+{
+ this.newMethod = DynamicKLineTitlePainting; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.YClose;
+ this.IsShowDate = false; //标题是否显示日期
+ this.IsShowName = true; //标题是否显示股票名字
+ this.Symbol;
+ this.UpperSymbol;
+ this.LastShowData; //保存最后显示的数据 给tooltip用
+ this.ClassName ='DynamicMinuteTitlePainting';
+ this.SpaceWidth = 2;
+ this.IsShowAveragePrice=true; //是否显示均线价格
+
+ this.GetCurrentKLineData = function () //获取当天鼠标位置所在的K线数据
+ {
+ if (this.LastShowData) return this.LastShowData;
+ if (this.CursorIndex == null || !this.Data) return null;
+ if (this.Data.length <= 0) return null;
+
+ var index = Math.abs(this.CursorIndex);
+ index = parseInt(index.toFixed(0));
+ var dataIndex = this.Data.DataOffset + index;
+ if (dataIndex >= this.Data.Data.length) dataIndex = this.Data.Data.length - 1;
+ if (dataIndex < 0) return null;
+
+ var item = this.Data.Data[dataIndex];
+ return item;
+ }
+
+ this.SendUpdateUIMessage = function (funcName) //通知外面 标题变了
+ {
+ if (!this.UpdateUICallback) return;
+
+ var sendData =
+ {
+ TitleName: '分钟标题', CallFunction: funcName, Stock: { Name: this.Name, Symbol: this.Symbol, },
+ Rect:
+ {
+ Left: this.Frame.ChartBorder.GetLeft(), Right: this.Frame.ChartBorder.GetRight(),
+ Top: 0, Bottom: this.Frame.ChartBorder.GetTop(),
+ }
+ };
+
+ //有数据
+ if (this.Data && this.Data.Data && this.Data.Data.length > 0) {
+ let index = this.Data.Data.length - 1; //默认最后1分钟的数据
+ if (this.CursorIndex) {
+ let cursorIndex = Math.abs(this.CursorIndex - 0.5);
+ cursorIndex = parseInt(cursorIndex.toFixed(0));
+ index = this.Data.DataOffset + cursorIndex;
+ if (index >= this.Data.Data.length) index = this.Data.Data.length - 1;
+ }
+
+ if (index >= 0) {
+ let item = this.Data.Data[index];
+ this.LastShowData = item;
+ sendData.Stock.Data =
+ {
+ Time: item.Time, Close: item.Close, AvPrice: item.AvPrice,
+ Vol: item.Vol, Amount: item.Amount
+ }
+ if (item.Time) sendData.Stock.Time = item.Time; //分钟K线才有时间
+ }
+ }
+ this.UpdateUICallback(sendData);
+ }
+
+ this.DrawTitle = function ()
+ {
+ this.UpperSymbol = this.Symbol ? this.Symbol.toUpperCase() : '';
+ this.SendUpdateUIMessage('DrawTitle');
+ this.OnDrawEventCallback(null, "DynamicMinuteTitlePainting::DrawTitle");
+ }
+
+ this.GetDecimal = function (symbol)
+ {
+ return JSCommonCoordinateData.GetfloatPrecision(symbol);//价格小数位数
+ }
+
+ this.DrawMulitLine = function (item) //画多行
+ {
+ var leftSpace = 5;
+ var bottomSpace = 2;
+ var left = this.Frame.ChartBorder.GetLeft() + leftSpace;;
+ var right = this.Frame.ChartBorder.GetRight();
+ var width = this.Frame.ChartBorder.GetWidth();
+ var height = this.Frame.ChartBorder.GetTop();
+
+ var defaultfloatPrecision = this.GetDecimal(this.Symbol); //价格小数位数
+ var itemHeight = (height - bottomSpace) / this.LineCount;
+ var bottom = itemHeight;
+
+ this.Canvas.textAlign = "left";
+ this.Canvas.textBaseline = "bottom";
+ this.Canvas.font = this.Font;
+ this.Canvas.fillStyle = this.UnchagneColor;
+
+ this.Canvas.fillStyle = this.UnchagneColor;
+ var text = IFrameSplitOperator.FormatDateTimeString(item.DateTime, this.IsShowDate ? 'YYYY-MM-DD' : 'HH-MM');
+ var timeWidth = this.Canvas.measureText(text).width + 5; //后空5个像素
+ this.Canvas.fillText(text, left, bottom, timeWidth);
+
+ if (this.IsShowDate) {
+ var text = IFrameSplitOperator.FormatDateTimeString(item.DateTime, 'HH-MM');
+ this.Canvas.fillText(text, left, bottom + itemHeight, timeWidth);
+ }
+
+ var itemWidth = (width - leftSpace - timeWidth) / 2;
+ left += timeWidth;
+
+ if (item.Close != null) {
+ this.Canvas.fillStyle = this.GetColor(item.Close, this.YClose);
+ var text = g_JSChartLocalization.GetText('Tooltip-Price', this.LanguageID) + item.Close.toFixed(defaultfloatPrecision);
+ this.Canvas.fillText(text, left, bottom, itemWidth);
+ left += itemWidth;
+ }
+
+ if (item.Increase != null) {
+ this.Canvas.fillStyle = this.GetColor(item.Increase, 0);
+ var text = g_JSChartLocalization.GetText('Tooltip-Increase', this.LanguageID) + item.Increase.toFixed(2) + '%';
+ this.Canvas.fillText(text, left, bottom, itemWidth);
+ left += itemWidth;
+ }
+
+ bottom += itemHeight; //换行
+ var left = this.Frame.ChartBorder.GetLeft() + leftSpace + timeWidth;
+
+ this.Canvas.fillStyle = this.VolColor;
+ var text = g_JSChartLocalization.GetText('Tooltip-Vol', this.LanguageID) + IFrameSplitOperator.FormatValueString(item.Vol, 2, this.LanguageID);
+ this.Canvas.fillText(text, left, bottom, itemWidth);
+ left += itemWidth;
+
+ this.Canvas.fillStyle = this.AmountColor;
+ var text = g_JSChartLocalization.GetText('Tooltip-Amount', this.LanguageID) + IFrameSplitOperator.FormatValueString(item.Amount, 2, this.LanguageID);
+ this.Canvas.fillText(text, left, bottom, itemWidth);
+ left += itemWidth;
+ }
+
+ this.DrawItem = function (item)
+ {
+ var isHScreen = this.Frame.IsHScreen === true;
+ var left = this.Frame.ChartBorder.GetLeft();;
+ var bottom = this.Frame.ChartBorder.GetTop() - this.Frame.ChartBorder.Top / 2;
+ var right = this.Frame.ChartBorder.GetRight();
+ var defaultfloatPrecision = this.GetDecimal(this.Symbol); //价格小数位数
+
+ if (isHScreen)
+ {
+ if (this.Frame.ChartBorder.Right < 5) return;
+ var left = 2;
+ var bottom = this.Frame.ChartBorder.Right / 2; //上下居中显示
+ var right = this.Frame.ChartBorder.GetHeight();
+ var xText = this.Frame.ChartBorder.GetChartWidth();
+ var yText = this.Frame.ChartBorder.GetTop();
+ this.Canvas.translate(xText, yText);
+ this.Canvas.rotate(90 * Math.PI / 180);
+ }
+ else
+ {
+ if (bottom < 5) return;
+ }
+
+ this.Canvas.textAlign = "left";
+ this.Canvas.textBaseline = "middle";
+ this.Canvas.font = this.Font;
+ var position = { Left: left, Bottom: bottom, IsHScreen: isHScreen };
+
+ if (this.IsShowName)
+ {
+ if (!this.DrawMinuteText(this.Name, this.NameColor, position, true)) return;
+ }
+
+ this.Canvas.fillStyle = this.UnchagneColor;
+ var text = IFrameSplitOperator.FormatDateTimeString(item.DateTime, this.IsShowDate ? 'YYYY-MM-DD HH-MM' : 'HH-MM');
+ if (!this.DrawMinuteText(text, this.DateTimeColor, position)) return;
+
+ if (IFrameSplitOperator.IsNumber(item.Close))
+ {
+ var color = this.GetColor(item.Close, this.YClose);
+ var text = g_JSChartLocalization.GetText('MTitle-Close', this.LanguageID) + item.Close.toFixed(defaultfloatPrecision);
+ if (!this.DrawMinuteText(text, color, position)) return;
+ }
+
+ if (IFrameSplitOperator.IsNumber(item.Increase))
+ {
+ var color = this.GetColor(item.Increase, 0);
+ var text = g_JSChartLocalization.GetText('MTitle-Increase', this.LanguageID) + item.Increase.toFixed(2) + '%';
+ if (!this.DrawMinuteText(text, color, position)) return;
+ }
+
+ if (IFrameSplitOperator.IsNumber(item.AvPrice) && this.IsShowAveragePrice==true)
+ {
+ var color = this.GetColor(item.AvPrice, this.YClose);
+ var text = g_JSChartLocalization.GetText('MTitle-AvPrice', this.LanguageID) + item.AvPrice.toFixed(defaultfloatPrecision);
+ if (!this.DrawMinuteText(text, color, position)) return;
+ }
+
+ if (IFrameSplitOperator.IsNumber(item.Vol))
+ {
+ var text = g_JSChartLocalization.GetText('MTitle-Vol', this.LanguageID) + IFrameSplitOperator.FormatValueString(item.Vol, 2, this.LanguageID);
+ if (!this.DrawMinuteText(text, this.VolColor, position)) return;
+ }
+
+ if (IFrameSplitOperator.IsNumber(item.Amount))
+ {
+ var text = g_JSChartLocalization.GetText('MTitle-Amount', this.LanguageID) + IFrameSplitOperator.FormatValueString(item.Amount, 2, this.LanguageID);
+ if (!this.DrawMinuteText(text, this.AmountColor, position)) return;
+ }
+
+ if (MARKET_SUFFIX_NAME.IsChinaFutures(this.UpperSymbol) && IFrameSplitOperator.IsNumber(item.Position))
+ {
+ var text = g_JSChartLocalization.GetText('MTitle-Position', this.LanguageID) + IFrameSplitOperator.FormatValueString(item.Position, 2, this.LanguageID);
+ if (!this.DrawMinuteText(text, this.VolColor, position)) return;
+ }
+
+ }
+
+ this.FullDraw=function()
+ {
+ this.Draw();
+ }
+
+ this.Draw = function ()
+ {
+ this.UpperSymbol = this.Symbol ? this.Symbol.toUpperCase() : '';
+ this.LastShowData = null;
+ this.SendUpdateUIMessage('Draw');
+ if (!this.IsShow) return;
+ if (this.CursorIndex == null || !this.Data || !this.Data.Data || this.Data.Data.length <= 0)
+ {
+ this.OnDrawEventCallback(null,"DynamicMinuteTitlePainting::Draw");
+ return;
+ }
+
+ var index = this.CursorIndex;
+ index = parseInt(index.toFixed(0));
+ var dataIndex = index + this.Data.DataOffset;
+ if (dataIndex >= this.Data.Data.length) dataIndex = this.Data.Data.length - 1;
+
+ var item = this.Data.Data[dataIndex];
+ this.LastShowData = item;
+ this.OnDrawEventCallback(item, "DynamicMinuteTitlePainting::Draw");
+
+ if (this.LineCount > 1 && !(this.Frame.IsHScreen === true))
+ {
+ this.DrawMulitLine(item);
+ return;
+ }
+
+ this.Canvas.save();
+ this.DrawItem(item);
+ this.Canvas.restore();
+ }
+
+ this.DrawMinuteText = function (title, color, position, isShow)
+ {
+ if (!title) return true;
+
+ var isHScreen = this.Frame.IsHScreen === true;
+ var right = this.Frame.ChartBorder.GetRight();
+ if (isHScreen) right = this.Frame.ChartBorder.GetHeight();
+
+ this.Canvas.fillStyle = color;
+ var textWidth = this.Canvas.measureText(title).width;
+ if (position.Left + textWidth > right) return false;
+ if (!(isShow === false)) this.Canvas.fillText(title, position.Left, position.Bottom, textWidth);
+
+ position.Left += textWidth + this.SpaceWidth;
+ return true;
+ }
+}
+
+//字符串输出格式
+var STRING_FORMAT_TYPE =
+{
+ DEFAULT: 1, //默认 2位小数 单位自动转化 (万 亿)
+ ORIGINAL: 2, //原始数据
+ THOUSANDS: 21, //千分位分割
+};
+
+function DynamicTitleData(data, name, color) //指标标题数据
+{
+ this.Data = data;
+ this.Name = name;
+ this.Color = color; //字体颜色
+ this.DataType; //数据类型
+ this.StringFormat = STRING_FORMAT_TYPE.DEFAULT; //字符串格式
+ this.FloatPrecision = 2; //小数位数
+ this.GetTextCallback; //自定义数据转文本回调
+ this.IsShow=true;
+}
+
+//指标标题
+function DynamicChartTitlePainting()
+{
+ this.newMethod = IChartTitlePainting; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.IsDynamic = true;
+ this.Data = new Array();
+ this.Explain;
+ this.TitleBG; //标题背景色
+ this.TitleBGHeight = 20; //标题背景色高度
+ this.TitleAlign = 'middle';//对其方式
+ this.TitleBottomDistance = 1; //标题靠底部输出的时候 字体和底部的间距
+ this.Text = new Array(); //副标题 Text:'文本', Color:'颜色'
+ this.EraseRect;
+ this.EraseColor = g_JSChartResource.BGColor; //用来擦出的背景色
+
+ this.TitleRect; //指标名字显示区域
+ this.IsDrawTitleBG=false; //是否绘制指标名字背景色
+ this.BGColor=g_JSChartResource.IndexTitleBGColor;
+
+ this.IsShowIndexName = true; //是否显示指标名字
+ this.ParamSpace = 2; //参数显示的间距
+ this.OutName=null; //动态标题
+ this.IsFullDraw=true; //手势离开屏幕以后是否显示最后的价格
+
+ this.SetDynamicOutName=function(outName, args)
+ {
+ if (!this.OutName) this.OutName=new Map();
+ else this.OutName.clear();
+
+ var mapArgs=new Map();
+ for(var i in args)
+ {
+ var item=args[i];
+ mapArgs.set(`{${item.Name}}`, item);
+ }
+
+ for(var i in outName)
+ {
+ var item=outName[i];
+ var aryFond = item.DynamicName.match(/{\w*}/i);
+ if (!aryFond || aryFond.length<=0)
+ {
+ this.OutName.set(item.Name, item.DynamicName);
+ }
+ else
+ {
+ var dyName=item.DynamicName;
+ var bFind=true;
+ for(var j=0;jthis.TitleRect.Left && xthis.TitleRect.Top && y 0) text += ',';
+
+ text += year.toString();
+ switch (quarter) {
+ case 1:
+ text += '一季报 ';
+ break;
+ case 2:
+ text += '半年报 ';
+ break;
+ case 3:
+ text += '三季报 ';
+ break;
+ case 4:
+ text += '年报 ';
+ break;
+ }
+
+ text += this.FormatValue(value, format);
+ }
+
+ return text;
+ }
+
+ this.SendUpdateUIMessage = function (funcName) //通知外面 标题变了
+ {
+ if (!this.UpdateUICallback) return;
+
+ var sendData = {
+ TitleName: '指标标题', CallFunction: funcName,
+ TitleData: { Title: this.Title, Identify: this.Frame.Identify, Data: [] },
+ Rect: //标题的位置
+ {
+ Top: this.Frame.ChartBorder.GetTop(), Left: this.Frame.ChartBorder.GetLeft(),
+ Right: this.Frame.ChartBorder.GetRight(), Bottom: this.Frame.ChartBorder.GetBottom()
+ }
+ };
+
+ for (var i in this.Data) {
+ var item = this.Data[i];
+ if (!item || !item.Data || !item.Data.Data) continue;
+ if (item.Data.Data.length <= 0) continue;
+
+ var titleItem = { Name: item.Name, Color: item.Color };
+ if (item.DataType) titleItem.DataType = item.DataType;
+
+ if (item.DataType == "StraightLine") //直线只有1个数据
+ {
+ titleItem.Value = item.Data.Data[0];
+ }
+ else {
+ var index = item.Data.Data.length - 1;
+ if (this.CursorIndex != null) {
+ var cursorIndex = Math.abs(this.CursorIndex - 0.5);
+ cursorIndex = parseInt(cursorIndex.toFixed(0));
+ index = item.Data.DataOffset + cursorIndex
+ }
+ if (index >= item.Data.Data.length) index = item.Data.Data.length - 1;
+
+ titleItem.Value = item.Data.Data[index];
+ }
+
+ sendData.TitleData.Data.push(titleItem);
+ }
+
+ //console.log('[DynamicChartTitlePainting::SendUpdateUIMessage', sendData);
+ this.UpdateUICallback(sendData);
+ }
+
+ this.FullDraw=function()
+ {
+ this.EraseRect = null;
+ this.TitleRect=null;
+ this.IsDrawTitleBG=this.Frame.IsDrawTitleBG;
+ if (this.Frame.ChartBorder.TitleHeight < 5) return;
+ if (this.Frame.IsShowTitle == false) return;
+ if (this.Frame.IsMinSize) return;
+
+ this.IsShowIndexName = this.Frame.IsShowIndexName;
+ this.ParamSpace = this.Frame.IndexParamSpace;
+
+ if (this.Frame.IsHScreen === true)
+ {
+ this.Canvas.save();
+ this.DrawItem(true,true);
+ this.Canvas.restore();
+ return;
+ }
+
+ this.DrawItem(true,true);
+ }
+
+ this.DrawTitle = function ()
+ {
+ this.IsDrawTitleBG=this.Frame.IsDrawTitleBG;
+ this.EraseRect = null;
+ this.TitleRect=null;
+ this.SendUpdateUIMessage('DrawTitle');
+ if (this.Frame.ChartBorder.TitleHeight < 5) return;
+ if (this.Frame.IsShowTitle == false) return;
+
+ this.IsShowIndexName = this.Frame.IsShowIndexName;
+ this.ParamSpace = this.Frame.IndexParamSpace;
+
+ if (this.Frame.IsHScreen === true)
+ {
+ this.Canvas.save();
+ this.DrawItem(true,false);
+ this.Canvas.restore();
+ return;
+ }
+
+ this.DrawItem(true,false);
+ }
+
+ this.EraseTitle = function ()
+ {
+ if (!this.EraseRect) return;
+ this.Canvas.fillStyle = this.EraseColor;
+ this.Canvas.fillRect(this.EraseRect.Left, this.EraseRect.Top, this.EraseRect.Width, this.EraseRect.Height);
+ }
+
+ this.Draw = function ()
+ {
+ this.TitleRect=null;
+ this.SendUpdateUIMessage('Draw');
+
+ if (this.CursorIndex == null) return;
+ if (!this.Data) return;
+ if (this.Frame.ChartBorder.TitleHeight < 5) return;
+ if (this.Frame.IsShowTitle == false) return;
+
+ this.IsShowIndexName = this.Frame.IsShowIndexName;
+ this.ParamSpace = this.Frame.IndexParamSpace;
+
+ if (this.Frame.IsHScreen === true)
+ {
+ this.Canvas.save();
+ this.DrawItem(false,true);
+ this.Canvas.restore();
+ return;
+ }
+
+ this.DrawItem(false,true);
+ }
+
+ this.DrawItem=function(bDrawTitle, bDrawValue)
+ {
+ var isHScreen=(this.Frame.IsHScreen === true);
+ var left = this.Frame.ChartBorder.GetLeft() + 1;
+ var bottom = this.Frame.ChartBorder.GetTop() + this.Frame.ChartBorder.TitleHeight / 2; //上下居中显示
+ if (this.TitleAlign == 'bottom') bottom = this.Frame.ChartBorder.GetTopEx() - this.TitleBottomDistance;
+ var right = this.Frame.ChartBorder.GetRight();
+ var textWidth;
+
+ if (isHScreen)
+ {
+ let xText = this.Frame.ChartBorder.GetRightTitle();
+ let yText = this.Frame.ChartBorder.GetTop();
+ this.Canvas.translate(xText, yText);
+ this.Canvas.rotate(90 * Math.PI / 180);
+ left = 1;
+ bottom = -(this.Frame.ChartBorder.TitleHeight / 2); //上下居中显示
+ if (this.TitleAlign == 'bottom') bottom = -this.TitleBottomDistance;
+ right = this.Frame.ChartBorder.GetHeight();
+ }
+
+ this.EraseTitle();
+
+ this.Canvas.textAlign = "left";
+ this.Canvas.textBaseline = this.TitleAlign;
+ this.Canvas.font = this.Font;
+
+ if (this.TitleBG && this.Title) //指标名称
+ {
+ textWidth = this.Canvas.measureText(this.Title).width + 2;
+ let height = this.Frame.ChartBorder.TitleHeight;
+ let top = this.Frame.ChartBorder.GetTop();
+ if (height > 20)
+ {
+ top += (height - 20) / 2 + (height - 45) / 2;
+ height = 20;
+ }
+
+ if (this.TitleAlign == 'bottom') //底部输出文字
+ {
+ top = this.Frame.ChartBorder.GetTopEx() - 20;
+ if (top < 0) top = 0;
+ }
+ if (bDrawTitle)
+ {
+ this.Canvas.fillStyle = this.TitleBG;
+ this.Canvas.fillRect(left, top, textWidth, height);
+ }
+ }
+
+ if (this.Title && this.IsShowIndexName) //指标参数
+ {
+ const metrics = this.Canvas.measureText(this.Title);
+ textWidth = metrics.width + 2;
+ if (bDrawTitle)
+ {
+ if (this.IsDrawTitleBG) //绘制指标名背景色
+ {
+ var spaceSize=1;
+ this.Canvas.fillStyle=this.BGColor;
+ if (isHScreen)
+ {
+ this.TitleRect= {Left:this.Frame.ChartBorder.GetRightTitle(),Top:this.Frame.ChartBorder.GetTop(),Width:this.Frame.ChartBorder.TitleHeight ,Height:textWidth}; //保存下标题的坐标
+ let drawRect={Left:left, Top:-this.Frame.ChartBorder.TitleHeight+spaceSize, Width:textWidth, Height:this.Frame.ChartBorder.TitleHeight-(spaceSize*2)};
+ this.Canvas.fillRect(drawRect.Left,drawRect.Top,drawRect.Width,drawRect.Height);
+ }
+ else
+ {
+ this.TitleRect={Left:left, Top:this.Frame.ChartBorder.GetTop()+spaceSize, Width:textWidth, Height:this.Frame.ChartBorder.TitleHeight-(spaceSize*2)}; //保存下标题的坐标
+ this.Canvas.fillRect(this.TitleRect.Left,this.TitleRect.Top,this.TitleRect.Width,this.TitleRect.Height);
+ }
+ }
+ this.Canvas.fillStyle = this.TitleColor;
+ this.Canvas.fillText(this.Title, left, bottom, textWidth);
+ }
+ left += textWidth;
+ }
+
+ if (this.Text && this.Text.length > 0)
+ {
+ for (let i in this.Text)
+ {
+ let item = this.Text[i];
+ this.Canvas.fillStyle = item.Color;
+ textWidth = this.Canvas.measureText(item.Text).width + 2;
+ this.Canvas.fillText(item.Text, left, bottom, textWidth);
+ left += textWidth;
+ }
+ }
+
+ if (bDrawValue)
+ {
+ for (var i in this.Data)
+ {
+ var item = this.Data[i];
+ if (!item || !item.Data || !item.Data.Data) continue;
+ if (item.Data.Data.length <= 0) continue;
+ if (item.IsShow==false) continue;
+
+ var value = null;
+ var valueText = null;
+ if (item.DataType == "StraightLine") //直线只有1个数据
+ {
+ value = item.Data.Data[0];
+ valueText = this.FormatValue(value, item);
+ }
+ else
+ {
+ var index = this.CursorIndex - 0.5;
+ if (index<0) index=0;
+ index = parseInt(index.toFixed(0));
+ if (item.Data.DataOffset + index >= item.Data.Data.length) continue;
+
+ value = item.Data.Data[item.Data.DataOffset + index];
+ if (value == null) continue;
+
+ if (item.DataType == "HistoryData-Vol")
+ {
+ value = value.Vol;
+ valueText = this.FormatValue(value, item);
+ }
+ else if (item.DataType == "MultiReport")
+ {
+ valueText = this.FormatMultiReport(value, item);
+ }
+ else
+ {
+ if (item.GetTextCallback) valueText = item.GetTextCallback(value, item);
+ else valueText = this.FormatValue(value, item);
+ }
+ }
+
+ this.Canvas.fillStyle = item.Color;
+
+ var text;
+ if (item.Name)
+ {
+ var dyTitle=this.GetDynamicOutName(item.Name);
+ if (dyTitle) text=dyTitle+ ":" + valueText;
+ else text = item.Name + ":" + valueText;
+ }
+ else
+ {
+ text=valueText;
+ }
+ textWidth = this.Canvas.measureText(text).width + this.ParamSpace; //后空2个像素
+ this.Canvas.fillText(text, left, bottom, textWidth);
+ left += textWidth;
+ }
+ }
+ else
+ {
+ left += 4;
+ var eraseRight = left, eraseLeft = left;
+ for (var i in this.Data)
+ {
+ var item = this.Data[i];
+ if (!item || !item.Data || !item.Data.Data) continue;
+ if (item.Data.Data.length <= 0) continue;
+
+ var indexName = '●' + item.Name;
+ this.Canvas.fillStyle = item.Color;
+ textWidth = this.Canvas.measureText(indexName).width + this.ParamSpace;
+ if (left + textWidth >= right) break;
+ this.Canvas.fillText(indexName, left, bottom, textWidth);
+ left += textWidth;
+ eraseRight = left;
+ }
+
+ if (eraseRight > eraseLeft)
+ {
+ if (isHScreen)
+ {
+ this.EraseRect =
+ {
+ Left: eraseLeft, Right: eraseRight, Top: -(this.Frame.ChartBorder.TitleHeight - 1),
+ Width: eraseRight - eraseLeft, Height: this.Frame.ChartBorder.TitleHeight - 2
+ };
+ }
+ else
+ {
+ this.EraseRect =
+ {
+ Left: eraseLeft, Right: eraseRight, Top: (this.Frame.ChartBorder.GetTop() + 1),
+ Width: eraseRight - eraseLeft, Height: this.Frame.ChartBorder.TitleHeight - 2
+ };
+ }
+ }
+ }
+ }
+}
+
+
+
+//导出统一使用JSCommon命名空间名
+module.exports =
+{
+ JSCommonChartTitle:
+ {
+ IChartTitlePainting: IChartTitlePainting,
+ DynamicKLineTitlePainting: DynamicKLineTitlePainting,
+ DynamicMinuteTitlePainting: DynamicMinuteTitlePainting,
+ DynamicChartTitlePainting: DynamicChartTitlePainting,
+ DynamicTitleData: DynamicTitleData,
+ STRING_FORMAT_TYPE: STRING_FORMAT_TYPE,
+ },
+
+ //单个类导出
+ JSCommonChartTitle_IChartTitlePainting: IChartTitlePainting,
+ JSCommonChartTitle_DynamicKLineTitlePainting: DynamicKLineTitlePainting,
+ JSCommonChartTitle_DynamicMinuteTitlePainting: DynamicMinuteTitlePainting,
+ JSCommonChartTitle_DynamicChartTitlePainting: DynamicChartTitlePainting,
+ JSCommonChartTitle_DynamicTitleData: DynamicTitleData,
+ JSCommonChartTitle_STRING_FORMAT_TYPE: STRING_FORMAT_TYPE,
+};
\ No newline at end of file
diff --git a/uni_modules/jones-hqchart2/js_sdk/umychart.complier.wechat.js b/uni_modules/jones-hqchart2/js_sdk/umychart.complier.wechat.js
new file mode 100644
index 0000000..60b650c
--- /dev/null
+++ b/uni_modules/jones-hqchart2/js_sdk/umychart.complier.wechat.js
@@ -0,0 +1,10644 @@
+/*
+ copyright (c) 2018 jones
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ 开源项目 https://github.com/jones2000/HQChart
+
+ jones_2000@163.com
+
+ 分析家语法编译器
+*/
+
+//日志
+import { JSConsole } from "./umychart.console.wechat.js"
+import { JSCommonData } from "./umychart.data.wechat.js"; //行情数据结构体 及涉及到的行情算法(复权,周期等)
+//配色资源
+import {
+ JSCommonResource_Global_JSChartResource as g_JSChartResource,
+ JSCommonResource_JSCHART_LANGUAGE_ID as JSCHART_LANGUAGE_ID,
+ JSCommonResource_Global_JSChartLocalization as g_JSChartLocalization,
+} from './umychart.resource.wechat.js'
+
+import
+{
+ JSCommonSplit_IFrameSplitOperator as IFrameSplitOperator,
+} from './umychart.framesplit.wechat.js'
+
+
+var g_JSComplierResource=
+{
+ Domain : "https://opensource.zealink.com", //API域名
+ CacheDomain : "https://opensourcecache.zealink.com", //缓存域名
+
+ CustomFunction: //定制函数
+ {
+ Data:new Map() //自定义函数 key=函数名, Value:{ID:函数名, Callback: }
+ },
+
+ CustomVariant: //自定义变量
+ {
+ Data:new Map() //自定义函数 key=变量名, Value:{ Name:变量名, Description:描述信息 }
+ },
+
+ IsCustomFunction:function(name)
+ {
+ if (g_JSComplierResource.CustomFunction.Data.has(name)) return true;
+ return false;
+ },
+
+ IsCustomVariant:function(name)
+ {
+ if (g_JSComplierResource.CustomVariant.Data.has(name)) return true;
+ return false;
+ }
+}
+
+var Messages = {
+ BadGetterArity: 'Getter must not have any formal parameters',
+ BadSetterArity: 'Setter must have exactly one formal parameter',
+ BadSetterRestParameter: 'Setter function argument must not be a rest parameter',
+ ConstructorIsAsync: 'Class constructor may not be an async method',
+ ConstructorSpecialMethod: 'Class constructor may not be an accessor',
+ DeclarationMissingInitializer: 'Missing initializer in %0 declaration',
+ DefaultRestParameter: 'Unexpected token =',
+ DuplicateBinding: 'Duplicate binding %0',
+ DuplicateConstructor: 'A class may only have one constructor',
+ DuplicateProtoProperty: 'Duplicate __proto__ fields are not allowed in object literals',
+ ForInOfLoopInitializer: '%0 loop variable declaration may not have an initializer',
+ GeneratorInLegacyContext: 'Generator declarations are not allowed in legacy contexts',
+ IllegalBreak: 'Illegal break statement',
+ IllegalContinue: 'Illegal continue statement',
+ IllegalExportDeclaration: 'Unexpected token',
+ IllegalImportDeclaration: 'Unexpected token',
+ IllegalLanguageModeDirective: 'Illegal \'use strict\' directive in function with non-simple parameter list',
+ IllegalReturn: 'Illegal return statement',
+ InvalidEscapedReservedWord: 'Keyword must not contain escaped characters',
+ InvalidHexEscapeSequence: 'Invalid hexadecimal escape sequence',
+ InvalidLHSInAssignment: 'Invalid left-hand side in assignment',
+ InvalidLHSInForIn: 'Invalid left-hand side in for-in',
+ InvalidLHSInForLoop: 'Invalid left-hand side in for-loop',
+ InvalidModuleSpecifier: 'Unexpected token',
+ InvalidRegExp: 'Invalid regular expression',
+ LetInLexicalBinding: 'let is disallowed as a lexically bound name',
+ MissingFromClause: 'Unexpected token',
+ MultipleDefaultsInSwitch: 'More than one default clause in switch statement',
+ NewlineAfterThrow: 'Illegal newline after throw',
+ NoAsAfterImportNamespace: 'Unexpected token',
+ NoCatchOrFinally: 'Missing catch or finally after try',
+ ParameterAfterRestParameter: 'Rest parameter must be last formal parameter',
+ Redeclaration: '%0 \'%1\' has already been declared',
+ StaticPrototype: 'Classes may not have static property named prototype',
+ StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode',
+ StrictDelete: 'Delete of an unqualified identifier in strict mode.',
+ StrictFunction: 'In strict mode code, functions can only be declared at top level or inside a block',
+ StrictFunctionName: 'Function name may not be eval or arguments in strict mode',
+ StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode',
+ StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode',
+ StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode',
+ StrictModeWith: 'Strict mode code may not include a with statement',
+ StrictOctalLiteral: 'Octal literals are not allowed in strict mode.',
+ StrictParamDupe: 'Strict mode function may not have duplicate parameter names',
+ StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode',
+ StrictReservedWord: 'Use of future reserved word in strict mode',
+ StrictVarName: 'Variable name may not be eval or arguments in strict mode',
+ TemplateOctalLiteral: 'Octal literals are not allowed in template strings.',
+ UnexpectedEOS: 'Unexpected end of input',
+ UnexpectedIdentifier: 'Unexpected identifier',
+ UnexpectedNumber: 'Unexpected number',
+ UnexpectedReserved: 'Unexpected reserved word',
+ UnexpectedString: 'Unexpected string',
+ UnexpectedTemplate: 'Unexpected quasi %0',
+ UnexpectedToken: 'Unexpected token %0',
+ UnexpectedTokenIllegal: 'Unexpected token ILLEGAL',
+ UnknownLabel: 'Undefined label \'%0\'',
+ UnterminatedRegExp: 'Invalid regular expression: missing /'
+};
+
+var Regex = {
+ // Unicode v8.0.0 NonAsciiIdentifierStart:
+ 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\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDF00-\uDF19]|\uD806[\uDCA0-\uDCDF\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1]|\uD87E[\uDC00-\uDE1D]/,
+ // Unicode v8.0.0 NonAsciiIdentifierPart:
+ 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\u3400-\u4DB5\u4E00-\u9FD5\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AD\uA7B0-\uA7B7\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA8FD\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2F\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDDFD\uDE80-\uDE9C\uDEA0-\uDED0\uDEE0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF7A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE38-\uDE3A\uDE3F\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE6\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC00-\uDC46\uDC66-\uDC6F\uDC7F-\uDCBA\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD00-\uDD34\uDD36-\uDD3F\uDD50-\uDD73\uDD76\uDD80-\uDDC4\uDDCA-\uDDCC\uDDD0-\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE37\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEEA\uDEF0-\uDEF9\uDF00-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3C-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF50\uDF57\uDF5D-\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC80-\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDB5\uDDB8-\uDDC0\uDDD8-\uDDDD\uDE00-\uDE40\uDE44\uDE50-\uDE59\uDE80-\uDEB7\uDEC0-\uDEC9\uDF00-\uDF19\uDF1D-\uDF2B\uDF30-\uDF39]|\uD806[\uDCA0-\uDCE9\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDEF0-\uDEF4\uDF00-\uDF36\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50-\uDF7E\uDF8F-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD836[\uDE00-\uDE36\uDE3B-\uDE6C\uDE75\uDE84\uDE9B-\uDE9F\uDEA1-\uDEAF]|\uD83A[\uDC00-\uDCC4\uDCD0-\uDCD6]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1]|\uD87E[\uDC00-\uDE1D]|\uDB40[\uDD00-\uDDEF]/
+}
+
+var Character =
+{
+ FromCodePoint: function (cp) {
+ return (cp < 0x10000) ? String.fromCharCode(cp) :
+ String.fromCharCode(0xD800 + ((cp - 0x10000) >> 10)) +
+ String.fromCharCode(0xDC00 + ((cp - 0x10000) & 1023));
+ },
+
+ //是否是空格 https://tc39.github.io/ecma262/#sec-white-space
+ IsWhiteSpace:function(cp)
+ {
+ return (cp === 0x20) || (cp === 0x09) || (cp === 0x0B) || (cp === 0x0C) || (cp === 0xA0) ||
+ (cp >= 0x1680 && [0x1680, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x202F, 0x205F, 0x3000, 0xFEFF].indexOf(cp) >= 0);
+ },
+
+ //是否换行 https://tc39.github.io/ecma262/#sec-line-terminators
+ IsLineTerminator:function(cp)
+ {
+ return (cp === 0x0A) || (cp === 0x0D) || (cp === 0x2028) || (cp === 0x2029);
+ },
+
+ // https://tc39.github.io/ecma262/#sec-names-and-keywords
+ IsIdentifierStart:function(cp)
+ {
+ return (cp === 0x24) || (cp === 0x5F) ||
+ (cp >= 0x41 && cp <= 0x5A) ||
+ (cp >= 0x61 && cp <= 0x7A) ||
+ (cp === 0x5C) ||
+ //【】
+ (cp===0x3010 || cp===0x3011) ||
+ ((cp >= 0x80) && Regex.NonAsciiIdentifierStart.test(Character.FromCodePoint(cp)));
+ },
+
+ IsIdentifierPart: function (cp)
+ {
+ return (cp === 0x24) || (cp === 0x5F) ||
+ (cp >= 0x41 && cp <= 0x5A) ||
+ (cp >= 0x61 && cp <= 0x7A) ||
+ (cp >= 0x30 && cp <= 0x39) ||
+ (cp === 0x5C) ||
+ //【】
+ (cp===0x3010 || cp===0x3011) ||
+ ((cp >= 0x80) && Regex.NonAsciiIdentifierPart.test(Character.FromCodePoint(cp)));
+ },
+
+ // https://tc39.github.io/ecma262/#sec-literals-numeric-literals
+ IsDecimalDigit: function (cp)
+ {
+ return (cp >= 0x30 && cp <= 0x39); // 0..9
+ },
+
+ IsHexDigit: function (cp)
+ {
+ return (cp >= 0x30 && cp <= 0x39) || (cp >= 0x41 && cp <= 0x46) || (cp >= 0x61 && cp <= 0x66); // a..f
+ },
+
+ isOctalDigit: function (cp)
+ {
+ return (cp >= 0x30 && cp <= 0x37); // 0..7
+ }
+}
+
+var TOKEN_NAME={};
+TOKEN_NAME[1 /* BooleanLiteral */] = 'Boolean';
+TOKEN_NAME[2 /* EOF */] = '';
+TOKEN_NAME[3 /* Identifier */] = 'Identifier';
+TOKEN_NAME[4 /* Keyword */] = 'Keyword';
+TOKEN_NAME[5 /* NullLiteral */] = 'Null';
+TOKEN_NAME[6 /* NumericLiteral */] = 'Numeric';
+TOKEN_NAME[7 /* Punctuator */] = 'Punctuator';
+TOKEN_NAME[8 /* StringLiteral */] = 'String';
+TOKEN_NAME[9 /* RegularExpression */] = 'RegularExpression';
+TOKEN_NAME[10 /* Template */] = 'Template';
+
+//编译异常, 错误类
+function ErrorHandler()
+{
+ this.Error=[];
+
+ this.RecordError=function(error)
+ {
+ this.Error.push(error);
+ }
+
+ this.ConstructError=function(msg,column)
+ {
+ let error=new Error(msg);
+ //通过自己抛异常并自己截获 来获取调用堆栈信息
+ try
+ {
+ throw error;
+ }
+ catch(base)
+ {
+ if (Object.create && Object.defineProperties)
+ {
+ error=Object.create(base);
+ error.Column=column;
+ }
+ }
+
+ return error;
+ }
+
+ this.CreateError=function(index, line, col, description)
+ {
+ let msg='Line ' + line + ': ' + description;
+ let error=this.ConstructError(msg,col);
+ error.Index=index;
+ error.LineNumber=line;
+ error.Description=description;
+ return error;
+ }
+
+ this.ThrowError=function(index, line, col, description)
+ {
+ let error=this.CreateError(index,line,col,description);
+ throw error;
+ }
+}
+
+//扫描类
+function Scanner(code, ErrorHandler)
+{
+ this.Source=code;
+ this.ErrorHandler=ErrorHandler;
+ this.Length=code.length;
+ this.Index=0;
+ this.LineNumber=(code.length>0)?1:0;
+ this.LineStart=0;
+ this.CurlyStack=[];
+
+ this.SaveState=function() //保存当前扫描状态
+ {
+ return { Index:this.Index, LineNumber:this.LineNumber, LineStart:this.LineStart };
+ }
+
+ this.RestoreState=function(state) //还原扫描状态
+ {
+ this.Index=state.Index;
+ this.LineNumber=state.LineNumber;
+ this.LineStart=state.LineStart;
+ }
+
+ this.IsEOF=function() //否是已经结束
+ {
+ return this.Index>=this.Length;
+ }
+
+ this.IsKeyword=function(id)
+ {
+ return false;
+ }
+
+ this.CodePointAt = function (i)
+ {
+ let cp = this.Source.charCodeAt(i);
+ if (cp >= 0xD800 && cp <= 0xDBFF)
+ {
+ let second = this.Source.charCodeAt(i + 1);
+ if (second >= 0xDC00 && second <= 0xDFFF) {
+ var first = cp;
+ cp = (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000;
+ }
+ }
+ return cp;
+ }
+
+ this.Lex=function()
+ {
+ if (this.IsEOF()) return { Type:2/*EOF*/, Value:'', LineNumber:this.LineNumber, LineStart:this.LineStart, Start:this.Index, End:this.Index };
+ let cp=this.Source.charCodeAt(this.Index);
+
+ //变量名 或 关键字
+ if (Character.IsIdentifierStart(cp)) return this.ScanIdentifier();
+
+ //( ) ; 开头 操作符扫描
+ if (cp === 0x28 || cp === 0x29 || cp === 0x3B) return this.ScanPunctuator();
+
+ //' " 开头 字符串扫描
+ if (cp === 0x27 || cp === 0x22) return this.ScanStringLiteral();
+
+ //. 开头 浮点型
+ if (cp==0x2E)
+ {
+ if (Character.IsDecimalDigit(this.Source.charCodeAt(this.Index + 1)))
+ return this.ScanNumericLiteral();
+
+ return this.ScanPunctuator();
+ }
+
+ //数字
+ if (Character.IsDecimalDigit(cp)) return this.ScanNumericLiteral();
+
+ if (cp >= 0xD800 && cp < 0xDFFF)
+ {
+ if (Character.IsIdentifierStart(this.CodePointAt(this.Index))) return this.ScanIdentifier();
+ }
+
+ return this.ScanPunctuator();
+
+ }
+
+ //关键字 变量名 https://tc39.github.io/ecma262/#sec-names-and-keywords
+ this.ScanIdentifier=function()
+ {
+ let type;
+ let start=this.Index;
+ //0x5C 反斜杠
+ let id=(this.Source.charCodeAt(start)=== 0x5C) ? this.GetComplexIdentifier() : this.GetIdentifier();
+
+ if (id.length) type=3; //Identifier
+ else if (this.IsKeyword(id)) type=4; //Keyword
+ else if (id==null) type=5; //NullLiteral
+ else if (id=='true' || id=='false') type=1; //BooleanLiteral
+ else type=3; //Identifier
+
+ if (type!=3 && (start+id.length!=this.Index))
+ {
+ let restore=this.Index;
+ this.Index=start;
+ throw Messages.InvalidEscapedReservedWord;
+ this.Index=restore;
+ }
+
+ if (id=='AND' || id=='OR') type=7 /*Punctuator*/;
+
+ return { Type:type, Value:id, LineNumber:this.LineNumber, LineStart:this.LineStart, Start:start, End:this.Index};
+ }
+
+ this.GetIdentifier=function()
+ {
+ let start=this.Index++; //start 保存进来的位置
+ while(!this.IsEOF())
+ {
+ let ch=this.Source.charCodeAt(this.Index);
+ if (ch==0x5C)
+ {
+ this.Index=start;
+ return this.GetComplexIdentifier();
+ }
+ else if (ch >= 0xD800 && ch < 0xDFFF)
+ {
+ this.Index=start;
+ return this.GetComplexIdentifier();
+ }
+
+ if (Character.IsIdentifierPart(ch)) ++this.Index;
+ else break;
+ }
+
+ return this.Source.slice(start,this.Index);
+ }
+
+ //操作符 https://tc39.github.io/ecma262/#sec-punctuators
+ this.ScanPunctuator=function()
+ {
+ let start=this.Index;
+ let str=this.Source[this.Index];
+ switch(str)
+ {
+ case '(':
+ ++this.Index;
+ break;
+ case ')':
+ case ';':
+ case ',':
+ ++this.Index;
+ break;
+ case '.':
+ ++this.Index;
+ /*if (this.Source[this.Index] === '.' && this.Source[this.Index + 1] === '.')
+ {
+ //Spread operator: ...
+ this.Index += 2;
+ str = '...';
+ }
+ */
+ break;
+ default:
+ str=this.Source.substr(this.Index,3);
+ if (str=='AND')
+ {
+ this.Index+=3;
+ }
+ else
+ {
+ str = this.Source.substr(this.Index, 2);
+ if (str === '&&' || str === '||' || str === '==' || str === '!=' || str === '<>' || str === '<=' || str === '>=' || str === '=>' || str==':=' || str=='OR')
+ {
+ this.Index += 2;
+ }
+ else
+ {
+ str=this.Source[this.Index];
+ if ('<>=!+-*%&|^/:'.indexOf(str) >= 0) ++this.Index;
+ }
+ }
+ }
+
+ if (this.Index==start)
+ this.ThrowUnecpectedToken();
+
+ return { Type:7/*Punctuator*/, Value:str, LineNumber:this.LineNumber, LineStart:this.LineStart, Start:start, End:this.Index };
+ }
+
+ //字符串 https://tc39.github.io/ecma262/#sec-literals-string-literals
+ this.ScanStringLiteral=function()
+ {
+ let start=this.Index;
+ let quote=this.Source[this.Index];
+
+ ++this.Index;
+ var octal=false;
+ let str='';
+ while(!this.IsEOF())
+ {
+ let ch=this.Source[this.Index++];
+ if (ch==quote)
+ {
+ quote='';
+ break;
+ }
+ else if (ch=='\\') //字符串转义
+ {
+ throw "not complete";
+ }
+ else if (Character.IsLineTerminator(ch.charCodeAt(0)))
+ {
+ break;
+ }
+ else
+ {
+ str+=ch;
+ }
+ }
+
+ if (quote!='')
+ {
+ this.Index=start;
+ this.ThrowUnecpectedToken();
+ }
+
+ return {Type:8/*StringLiteral*/, Value:str, LineNumber:this.LineNumber, LineStart:this.LineStart, Start:start, End:this.Index};
+ }
+
+ this.ScanNumericLiteral=function()
+ {
+ let start=this.Index;
+ let ch=this.Source[this.Index];
+ let num='';
+ if (ch!='.')
+ {
+ num=this.Source[this.Index++];
+ ch=this.Source[this.Index];
+ // Hex number starts with '0x'. 16进制
+ if (num=='0')
+ {
+ if (ch=='x' || ch=='X')
+ {
+ ++this.Index;
+ return this.ScanHexLiteral(start);
+ }
+ }
+
+ while(Character.IsDecimalDigit(this.Source.charCodeAt(this.Index)))
+ {
+ num+=this.Source[this.Index++];
+ }
+
+ ch=this.Source[this.Index];
+ }
+
+ if (ch=='.')
+ {
+ num+=this.Source[this.Index++];
+ while(Character.IsDecimalDigit(this.Source.charCodeAt(this.Index)))
+ {
+ num+=this.Source[this.Index++];
+ }
+ ch=this.Source[this.Index];
+ }
+
+ //科学计数法
+ if (ch=='e' || ch=='E')
+ {
+ num+=this.Source[this.Index++];
+ ch=this.Source[this.Index];
+ if (ch=='+' || ch=='-') num+=this.Source[this.Index];
+ if (Character.IsDecimalDigit(this.Source.charCodeAt(this.Index)))
+ {
+ while(Character.IsDecimalDigit(this.Source.charCodeAt(this.Index)))
+ {
+ num+=this.Source[this.Index++];
+ }
+ }
+ else
+ {
+ this.ThrowUnecpectedToken();
+ }
+ }
+
+ if (Character.IsIdentifierStart(this.Source.charCodeAt(this.Index)))
+ {
+ this.ThrowUnecpectedToken();
+ }
+
+ return { Type:6/*NumericLiteral*/, Value:parseFloat(num), LineNumber:this.LineNumber, LineStart:this.LineStart, Start:start, End:this.Index };
+ }
+
+ //空格 或 注释
+ this.ScanComments=function()
+ {
+ let comments;
+ let start=(this.Index==0);
+ while(!this.IsEOF())
+ {
+ let ch=this.Source.charCodeAt(this.Index);
+ if (Character.IsWhiteSpace(ch)) //过滤掉空格
+ {
+ ++this.Index;
+ }
+ else if (Character.IsLineTerminator(ch))
+ {
+ ++this.Index;
+ if (ch==0x0D && this.Source.charCodeAt(this.Index)==0x0A) ++this.Index; //回车+换行
+ ++this.LineNumber;
+ this.LineStart=this.Index;
+ start=true;
+ }
+ else if (ch==0x2F) // //注释
+ {
+ ch=this.Source.charCodeAt(this.Index+1);
+ if (ch==0x2F)
+ {
+ this.Index+=2;
+ let comment=this.SkipSingleLineComment(2);
+ start=true;
+ }
+ else
+ {
+ break;
+ }
+ }
+ else if (ch == 0x7B) //{ } 注释
+ {
+ this.Index += 1;
+ let comment = this.SkipMultiLineComment();
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ return comments;
+ }
+
+ this.SkipMultiLineComment = function ()
+ {
+ var comments = [];
+ while (!this.IsEOF())
+ {
+ var ch = this.Source.charCodeAt(this.Index);
+ if (Character.IsLineTerminator(ch))
+ {
+ ++this.LineNumber;
+ ++this.Index;
+ this.LineStart = this.Index;
+ }
+ else if (ch == 0x7D)
+ {
+ this.Index += 1;
+ return comments;
+ }
+ else
+ {
+ ++this.Index;
+ }
+ }
+
+ return comments;
+ }
+
+ //单行注释 https://tc39.github.io/ecma262/#sec-comments
+ this.SkipSingleLineComment=function(offset)
+ {
+ let comments=[];
+ while(!this.IsEOF())
+ {
+ let ch=this.Source.charCodeAt(this.Index);
+ ++this.Index;
+ if (Character.IsLineTerminator(ch))
+ {
+ if (ch === 13 && this.Source.charCodeAt(this.Index) === 10)
+ ++this.Index;
+
+ ++this.LineNumber;
+ this.LineStart=this.Index;
+ return comments;
+ }
+ }
+
+ return comments;
+ }
+
+ this.ThrowUnecpectedToken=function(message)
+ {
+ if (!message) message = Messages.UnexpectedTokenIllegal;
+ return this.ErrorHandler.ThrowError(this.Index, this.LineNumber, this.Index - this.LineStart + 1, message);
+ }
+
+}
+
+function Tokenizer(code)
+{
+ this.ErrorHandler=new ErrorHandler(); //错误信息处理类
+ this.Scanner=new Scanner(code,this.ErrorHandler);
+ this.Buffer=[];
+
+ this.GetNextToken=function()
+ {
+ if (this.Buffer.length==0)
+ {
+ let comments=this.Scanner.ScanComments();
+ if (!this.Scanner.IsEOF())
+ {
+ let token=this.Scanner.Lex();
+
+ let entry={ Type:TOKEN_NAME[token.Type], Value:this.Scanner.Source.slice(token.Start, token.End)};
+
+ this.Buffer.push(entry);
+ }
+ }
+
+ return this.Buffer.shift();
+ }
+}
+
+var Syntax = {
+ AssignmentExpression: 'AssignmentExpression',
+ AssignmentPattern: 'AssignmentPattern',
+ ArrayExpression: 'ArrayExpression',
+ ArrayPattern: 'ArrayPattern',
+ ArrowFunctionExpression: 'ArrowFunctionExpression',
+ AwaitExpression: 'AwaitExpression',
+ BlockStatement: 'BlockStatement',
+ BinaryExpression: 'BinaryExpression',
+ BreakStatement: 'BreakStatement',
+ CallExpression: 'CallExpression',
+ CatchClause: 'CatchClause',
+ ClassBody: 'ClassBody',
+ ClassDeclaration: 'ClassDeclaration',
+ ClassExpression: 'ClassExpression',
+ ConditionalExpression: 'ConditionalExpression',
+ ContinueStatement: 'ContinueStatement',
+ DoWhileStatement: 'DoWhileStatement',
+ DebuggerStatement: 'DebuggerStatement',
+ EmptyStatement: 'EmptyStatement',
+ ExportAllDeclaration: 'ExportAllDeclaration',
+ ExportDefaultDeclaration: 'ExportDefaultDeclaration',
+ ExportNamedDeclaration: 'ExportNamedDeclaration',
+ ExportSpecifier: 'ExportSpecifier',
+ ExpressionStatement: 'ExpressionStatement',
+ ForStatement: 'ForStatement',
+ ForOfStatement: 'ForOfStatement',
+ ForInStatement: 'ForInStatement',
+ FunctionDeclaration: 'FunctionDeclaration',
+ FunctionExpression: 'FunctionExpression',
+ Identifier: 'Identifier',
+ IfStatement: 'IfStatement',
+ ImportDeclaration: 'ImportDeclaration',
+ ImportDefaultSpecifier: 'ImportDefaultSpecifier',
+ ImportNamespaceSpecifier: 'ImportNamespaceSpecifier',
+ ImportSpecifier: 'ImportSpecifier',
+ Literal: 'Literal',
+ LabeledStatement: 'LabeledStatement',
+ LogicalExpression: 'LogicalExpression',
+ MemberExpression: 'MemberExpression',
+ MetaProperty: 'MetaProperty',
+ MethodDefinition: 'MethodDefinition',
+ NewExpression: 'NewExpression',
+ ObjectExpression: 'ObjectExpression',
+ ObjectPattern: 'ObjectPattern',
+ Program: 'Program',
+ Property: 'Property',
+ RestElement: 'RestElement',
+ ReturnStatement: 'ReturnStatement',
+ SequenceExpression: 'SequenceExpression',
+ SpreadElement: 'SpreadElement',
+ Super: 'Super',
+ SwitchCase: 'SwitchCase',
+ SwitchStatement: 'SwitchStatement',
+ TaggedTemplateExpression: 'TaggedTemplateExpression',
+ TemplateElement: 'TemplateElement',
+ TemplateLiteral: 'TemplateLiteral',
+ ThisExpression: 'ThisExpression',
+ ThrowStatement: 'ThrowStatement',
+ TryStatement: 'TryStatement',
+ UnaryExpression: 'UnaryExpression',
+ UpdateExpression: 'UpdateExpression',
+ VariableDeclaration: 'VariableDeclaration',
+ VariableDeclarator: 'VariableDeclarator',
+ WhileStatement: 'WhileStatement',
+ WithStatement: 'WithStatement',
+ YieldExpression: 'YieldExpression'
+};
+
+
+function Node()
+{
+ this.IsNeedIndexData=false; //是否需要大盘数据
+ this.IsNeedLatestData=false; //是否需要最新的个股行情数据
+ this.IsNeedSymbolData=false; //是否需要下载股票数据
+ this.IsNeedMarginData = new Set();
+ this.IsNeedNewsAnalysisData = new Set(); //新闻统计数据
+ this.IsNeedBlockIncreaseData = new Set(); //是否需要市场涨跌股票数据统计
+ this.IsNeedSymbolExData = new Set(); //下载股票行情的其他数据
+
+ this.FunctionData=[]; //{ID:, Args:, FunctionName: }
+ //FINVALUE(ID),FINONE(ID,Y,MMDD), FINANCE(ID)
+
+ this.IsAPIData = [] //加载API数据
+
+ this.GetDataJobList=function() //下载数据任务列表
+ {
+ let jobs=[];
+ if (this.IsNeedSymbolData) jobs.push({ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SYMBOL_DATA});
+ if (this.IsNeedIndexData) jobs.push({ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_INDEX_DATA});
+ if (this.IsNeedLatestData) jobs.push({ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SYMBOL_LATEST_DATA});
+
+ //涨跌停家数统计
+ for (var blockSymbol of this.IsNeedBlockIncreaseData)
+ {
+ jobs.push({ ID: JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_INDEX_INCREASE_DATA, Symbol: blockSymbol });
+ }
+
+ //加载融资融券
+ for (var jobID of this.IsNeedMarginData)
+ {
+ jobs.push({ID:jobID});
+ }
+
+ //加载新闻统计
+ for (var jobID of this.IsNeedNewsAnalysisData)
+ {
+ jobs.push({ID:jobID});
+ }
+
+ for (var i in this.IsAPIData)
+ {
+ var item = this.IsAPIData[i];
+ jobs.push(item);
+ }
+
+ //行情其他数据
+ for (var jobID of this.IsNeedSymbolExData)
+ {
+ jobs.push({ ID:jobID });
+ }
+
+ for(var i in this.FunctionData)
+ {
+ var item=this.FunctionData[i];
+ jobs.push(item);
+ }
+
+ return jobs;
+ }
+
+ this.VerifySymbolVariable = function (varName, token)
+ {
+ let setIndexName = new Set(['INDEXA', 'INDEXC', 'INDEXH', 'INDEXL', "INDEXO", "INDEXV", 'INDEXDEC', 'INDEXADV']);
+ if (setIndexName.has(varName))
+ {
+ this.IsNeedIndexData=true;
+ return;
+ }
+
+ let setSymbolDataName=new Set(['CLOSE','C','VOL','V','OPEN','O','HIGH','H','LOW','L','AMOUNT']);
+ if (setSymbolDataName.has(varName))
+ {
+ this.IsNeedSymbolData=true;
+ return;
+ }
+
+ if (varName === 'VOLR')
+ {
+ if (!this.IsNeedSymbolExData.has(JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_VOLR_DATA))
+ this.IsNeedSymbolExData.add(JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_VOLR_DATA);
+ return;
+ }
+
+ //CAPITAL流通股本(手), EXCHANGE 换手率, TOTALCAPITAL 总股本(手)
+ let setVariantName=new Set(
+ [
+ "CAPITAL","TOTALCAPITAL","EXCHANGE",
+ "HYBLOCK","DYBLOCK","GNBLOCK","FGBLOCK","ZSBLOCK","ZHBLOCK","ZDBLOCK","HYZSCODE",
+ "GNBLOCKNUM","FGBLOCKNUM","ZSBLOCKNUM","ZHBLOCKNUM","ZDBLOCKNUM",
+ "HYSYL","HYSJL"
+ ]);
+ if (setVariantName.has(varName))
+ {
+ var item={ ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_VARIANT, VariantName:varName };
+ if (token) item.Token={ Index:token.Start, Line:token.LineNumber };
+ this.FunctionData.push(item);
+ return;
+ }
+
+ if (g_JSComplierResource.IsCustomVariant(varName)) //自定义函数
+ {
+ var item={ VariantName:varName, ID:JS_EXECUTE_JOB_ID.JOB_CUSTOM_VARIANT_DATA };
+ if (token) item.Token={ Index:token.Start, Line:token.LineNumber };
+ this.FunctionData.push(item);
+ return;
+ }
+ }
+
+ this.VerifySymbolFunction = function (callee, args, token)
+ {
+ //自定义函数 可以覆盖系统内置函数
+ if (g_JSComplierResource.IsCustomFunction(callee.Name))
+ {
+ var item={FunctionName:callee.Name, ID:JS_EXECUTE_JOB_ID.JOB_CUSTOM_FUNCTION_DATA, Args:args}
+ if (token) item.Token={ Index:token.Start, Line:token.LineNumber};
+ this.FunctionData.push(item);
+ return;
+ }
+
+ if (callee.Name=='DYNAINFO')
+ {
+ this.IsNeedLatestData=true;
+ return;
+ }
+
+ //财务函数
+ if (callee.Name=='FINANCE')
+ {
+ var item={ ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_FINANCE, Args:args, FunctionName:callee.Name };
+ if (token) item.Token={ Index:token.Start, Line:token.LineNumber };
+ this.FunctionData.push(item);
+ return;
+ }
+
+ if (callee.Name=="FINVALUE")
+ {
+ var item={ ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_FINVALUE, Args:args, FunctionName:callee.Name };
+ if (token) item.Token={ Index:token.Start, Line:token.LineNumber };
+ this.FunctionData.push(item);
+ return;
+ }
+
+ if (callee.Name=="FINONE")
+ {
+ var item={ ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_FINONE, Args:args, FunctionName:callee.Name };
+ if (token) item.Token={ Index:token.Start, Line:token.LineNumber };
+ this.FunctionData.push(item);
+ return;
+ }
+
+ if (callee.Name=='GPJYVALUE')
+ {
+ var item={ ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_GPJYVALUE, Args:args, FunctionName:callee.Name };
+ if (token) item.Token={ Index:token.Start, Line:token.LineNumber };
+ this.FunctionData.push(item);
+ return;
+ }
+
+ if (callee.Name === 'MARGIN')
+ {
+ let jobID = JS_EXECUTE_JOB_ID.GetMarginJobID(args[0].Value);
+ if (jobID && !this.IsNeedMarginData.has(jobID)) this.IsNeedMarginData.add(jobID);
+ return;
+ }
+
+ if (callee.Name === 'NEWS')
+ {
+ let jobID = JS_EXECUTE_JOB_ID.GetNewsAnalysisID(args[0].Value);
+ if (jobID && !this.IsNeedNewsAnalysisData.has(jobID)) this.IsNeedNewsAnalysisData.add(jobID);
+ return;
+ }
+
+ if (callee.Name == 'COST' || callee.Name == 'WINNER') //筹码都需要换手率
+ {
+ //下载流通股
+ var item={ ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_FINANCE, Args:[7], FunctionName:"FINANCE", FunctionName2:callee.Name };
+ if (token) item.Token={ Index:token.Start, Line:token.LineNumber };
+ this.FunctionData.push(item);
+ return;
+ }
+
+ if (callee.Name=="INBLOCK")
+ {
+ var item={ ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_VARIANT, VariantName:"INBLOCK" }; //下载所有板块
+ if (token) item.Token={ Index:token.Start, Line:token.LineNumber };
+ this.FunctionData.push(item);
+ return;
+ }
+
+ if (callee.Name === 'BETA') //beta需要下载上证指数
+ {
+ this.IsNeedIndexData = true;
+ return;
+ }
+
+ if (callee.Name == 'UPCOUNT' || callee.Name == 'DOWNCOUNT') //上涨下跌个数
+ {
+ var blockSymbol = args[0].Value;
+ if (!this.IsNeedBlockIncreaseData.has(blockSymbol)) this.IsNeedBlockIncreaseData.add(blockSymbol);
+ return;
+ }
+
+ if (callee.Name == "LOADAPIDATA") //加载API数据
+ {
+ var item = { Name: callee.Name, ID: JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_CUSTOM_API_DATA, Args: args };
+ if (token) item.Token = { Index: token.Start, Line: token.LineNumber };
+
+ this.IsAPIData.push(item);
+ return;
+ }
+ }
+
+ this.ExpressionStatement=function(expression)
+ {
+ return { Type:Syntax.ExpressionStatement, Expression:expression };
+ }
+
+ this.Script=function(body)
+ {
+ return {Type:Syntax.Program, Body:body, SourceType:'通达信脚本' };
+ }
+
+ this.SequenceExpression=function(expression)
+ {
+ return {Type:Syntax.SequenceExpression, Expression:expression };
+ }
+
+ this.BinaryExpression=function(operator, left, right)
+ {
+ let logical = (operator === '||' || operator === '&&' || operator=='AND' || operator=='OR');
+ let type = logical ? Syntax.LogicalExpression : Syntax.BinaryExpression;
+
+ return { Type:type, Operator:operator, Left:left, Right:right };
+ }
+
+ this.Literal=function(value,raw)
+ {
+ return { Type:Syntax.Literal, Value:value, Raw:raw };
+ }
+
+ this.Identifier = function (name, token)
+ {
+ this.VerifySymbolVariable(name, token);
+
+ return { Type:Syntax.Identifier, Name:name};
+ }
+
+ this.AssignmentExpression=function (operator, left, right)
+ {
+ return { Type:Syntax.AssignmentExpression, Operator:operator, Left:left, Right:right };
+ }
+
+ this.UnaryExpression=function(operator, argument)
+ {
+ return { Type:Syntax.UnaryExpression, Operator:operator, Argument:argument, Prefix:true };
+ }
+
+ this.EmptyStatement=function()
+ {
+ return { Type:Syntax.EmptyStatement };
+ }
+
+ this.CallExpression = function (callee, args, token)
+ {
+ this.VerifySymbolFunction(callee, args, token);
+
+ return { Type:Syntax.CallExpression, Callee:callee, Arguments:args };
+ }
+
+ this.StaticMemberExpression = function (object, property)
+ {
+ return { Type: Syntax.MemberExpression, Computed: false, Object: object, Property: property };
+ }
+}
+
+
+
+function JSParser(code)
+{
+ this.ErrorHandler=new ErrorHandler();
+ this.Scanner=new Scanner(code, this.ErrorHandler);
+ this.Node=new Node(); //节点创建
+
+ this.LookAhead={Type:2, Value:'', LineNumber:this.Scanner.LineNumber, LineStart:0, Start:0, End:0 };
+ this.HasLineTerminator=false;
+ this.Context = {
+ IsModule: false,
+ await: false,
+ allowIn: true,
+ allowStrictDirective: true,
+ allowYield: true,
+ FirstCoverInitializedNameError: null,
+ IsAssignmentTarget: false,
+ IsBindingElement: false,
+ InFunctionBody: false,
+ inIteration: false,
+ inSwitch: false,
+ labelSet: {},
+ Strict: false
+ };
+
+ this.PeratorPrecedence =
+ {
+ ')': 0,
+ ';': 0,
+ ',': 0,
+ ']': 0,
+ '||': 1,
+ 'OR':1,
+ '&&': 2,
+ 'AND':2,
+ '|': 3,
+ '^': 4,
+ '&': 5,
+ '=': 6,
+ '==': 6,
+ '!=': 6,
+ '<>': 6,
+ '===': 6,
+ '!==': 6,
+ '<': 7,
+ '>': 7,
+ '<=': 7,
+ '>=': 7,
+ '<<': 8,
+ '>>': 8,
+ '>>>': 8,
+ '+': 9,
+ '-': 9,
+ '*': 11,
+ '/': 11,
+ '%': 11
+ };
+
+ this.StartMarker={Index:0, Line: this.Scanner.LineNumber, Column:0 };
+ this.LastMarker={Index:0, Line: this.Scanner.LineNumber, Column:0 };
+
+ this.Initialize=function()
+ {
+ this.NextToken();
+ this.LastMarker={ Index:this.Scanner.Index, Line:this.Scanner.LineNumber, Column:this.Scanner.Index-this.Scanner.LineStart };
+ }
+
+
+ this.CreateNode=function()
+ {
+ return { Index:this.StartMarker.Index, Line:this.StartMarker.Line, Column:this.StartMarker.Column };
+ }
+
+ this.StartNode=function(token, lastLineStart)
+ {
+ if (lastLineStart==void 0) { lastLineStart=0; }
+
+ let column = token.Start - token.LineStart;
+ let line = token.LineNumber;
+ if (column < 0)
+ {
+ column += lastLineStart;
+ line--;
+ }
+
+ return { Index: token.Start, Line: line, Column: column };
+ }
+
+ this.Match=function(value)
+ {
+ return this.LookAhead.Type==7 /*Punctuator*/ && this.LookAhead.Value==value;
+ }
+
+ this.Expect=function(value)
+ {
+ let token=this.NextToken();
+ if (token.Type!=7 /*Punctuator*/ || token.Value!=value)
+ this.ThrowUnexpectedToken(token);
+ }
+
+ //是否是赋值操作符
+ this.MatchAssign=function()
+ {
+ if (this.LookAhead.Type!=7 /*Punctuator*/) return false;
+ let op=this.LookAhead.Value;
+
+ return op==':' || op==':=';
+ }
+
+ this.GetTokenRaw=function(token)
+ {
+ return this.Scanner.Source.slice(token.Start, token.End);
+ }
+
+ this.NextToken=function()
+ {
+ let token=this.LookAhead;
+ this.LastMarker.Index=this.Scanner.Index;
+ this.LastMarker.Line=this.Scanner.LineNumber;
+ this.LastMarker.Column=this.Scanner.Index-this.Scanner.LineStart;
+ this.CollectComments(); //过滤注释 空格
+
+ if (this.Scanner.Index !== this.StartMarker.Index)
+ {
+ this.StartMarker.Index = this.Scanner.Index;
+ this.StartMarker.Line = this.Scanner.LineNumber;
+ this.StartMarker.Column = this.Scanner.Index - this.Scanner.LineStart;
+ }
+
+ let next=this.Scanner.Lex();
+ this.HasLineTerminator=(token.LineNumber!=next.LineNumber);
+ if (next && this.Context.Strict && next.Type==3/*Identifier */)
+ {
+ //TODO:
+ }
+
+ this.LookAhead=next;
+
+ return token;
+ }
+
+ this.CollectComments=function()
+ {
+ this.Scanner.ScanComments();
+ }
+
+ this.ParseScript=function()
+ {
+ let node=this.CreateNode();
+ let body=this.ParseDirectivePrologues();
+
+ while(this.LookAhead.Type!=2 /*EOF*/)
+ {
+ body.push(this.ParseStatementListItem())
+ }
+
+ return this.Finalize(node,this.Node.Script(body));
+ }
+
+ //https://tc39.github.io/ecma262/#sec-directive-prologues-and-the-use-strict-directive
+ this.ParseDirective=function()
+ {
+ let token=this.LookAhead;
+ let node=this.CreateNode();
+ let expr=this.ParseExpression();
+ }
+
+ this.ParseDirectivePrologues=function()
+ {
+ let firstRestricted=null;
+ let body=[];
+ while(true)
+ {
+ let token=this.LookAhead;
+ if (token.Type!=8 /*StringLiteral*/) break;
+
+ let statement=this.ParseDirective();
+ body.push(statement);
+ }
+
+ return body;
+ }
+
+ // https://tc39.github.io/ecma262/#sec-block
+ this.ParseStatementListItem=function()
+ {
+ let statement;
+ this.Context.IsAssignmentTarget=true;
+ this.Context.IsBindingElement=true;
+ if (this.LookAhead.Type==4 /*Keyword*/)
+ {
+
+ }
+ else
+ {
+ statement=this.ParseStatement();
+ }
+
+ return statement;
+ }
+
+ // https://tc39.github.io/ecma262/#sec-ecmascript-language-statements-and-declarations
+ this.ParseStatement=function()
+ {
+ let statement;
+ switch(this.LookAhead.Type)
+ {
+ case 1 /* BooleanLiteral */:
+ case 5 /* NullLiteral */:
+ case 6 /* NumericLiteral */:
+ case 8 /* StringLiteral */:
+ case 10 /* Template */:
+ case 9 /* RegularExpression */:
+ statement = this.ParseExpressionStatement();
+ break;
+ case 7 /* Punctuator */:
+ let value = this.LookAhead.Value;
+ if (value === '(') statement = this.ParseExpressionStatement();
+ else if (value === ';') statement = this.ParseEmptyStatement();
+ else statement = this.ParseExpressionStatement();
+ break;
+ case 3 /* Identifier */:
+ statement = this.ParseLabelledStatement();
+ break;
+ case 4 /* Keyword */:
+ break;
+ default:
+ statement="error";
+ }
+
+ return statement;
+ }
+
+ // https://tc39.github.io/ecma262/#sec-empty-statement
+ this.ParseEmptyStatement=function()
+ {
+ let node=this.CreateNode();
+ this.Expect(';');
+ return this.Finalize(node, this.Node.EmptyStatement());
+ }
+
+ //https://tc39.github.io/ecma262/#sec-labelled-statements
+ this.ParseLabelledStatement=function()
+ {
+ let node=this.CreateNode();
+ let expr=this.ParseExpression();
+ this.ConsumeSemicolon();
+ let statement = new this.Node.ExpressionStatement(expr);
+
+ return this.Finalize(node, statement);
+ }
+
+ // https://tc39.github.io/ecma262/#sec-comma-operator
+ this.ParseExpression=function()
+ {
+ let startToken=this.LookAhead;
+ let expr=this.IsolateCoverGrammar(this.ParseAssignmentExpression);
+ if (this.Match(','))
+ {
+ let expressions=[];
+ expressions.push(expr);
+ while(this.LookAhead.Type!=2 /*EOF*/)
+ {
+ if (!this.Match(',')) break;
+ this.NextToken();
+ expressions.push(this.IsolateCoverGrammar(this.ParseAssignmentExpression));
+ }
+
+ expr=this.Finalize(this.StartNode(startToken),this.Node.SequenceExpression(expressions));
+ }
+
+ return expr;
+ }
+
+ this.ParseAssignmentExpression=function()
+ {
+ let expr;
+
+ let startToken=this.LookAhead;
+ let token=startToken;
+ expr=this.ParseConditionalExpression();
+
+ if (this.MatchAssign())
+ {
+ if (!this.Context.IsAssignmentTarget)
+ {
+ let marker=expr.Marker;
+ this.ThrowUnexpectedError(marker.Index,marker.Line,marker.Column,Messages.InvalidLHSInAssignment);
+ }
+
+ if (!this.Match('=') && !this.Match(':'))
+ {
+ this.Context.IsAssignmentTarget=false;
+ this.Context.IsBindingElement=false;
+ }
+ else
+ {
+ this.ReinterpretExpressionAsPattern(expr);
+ }
+
+ token=this.NextToken();
+ let operator=token.Value;
+ let right=this.IsolateCoverGrammar(this.ParseAssignmentExpression);
+ expr=this.Finalize(this.StartNode(startToken), this.Node.AssignmentExpression(operator, expr, right));
+ this.Context.FirstCoverInitializedNameError=null;
+ }
+
+ return expr;
+ }
+
+ this.ParseConditionalExpression=function()
+ {
+ let startToken=this.LookAhead;
+ let expr=this.InheritCoverGrammar(this.ParseBinaryExpression);
+
+ return expr;
+ }
+
+ this.ParseBinaryExpression=function()
+ {
+ let startToken=this.LookAhead;
+ let expr=this.InheritCoverGrammar(this.ParseExponentiationExpression);
+ let token=this.LookAhead;
+ var prec=this.BinaryPrecedence(token);
+ if (prec>0)
+ {
+ this.NextToken();
+ this.Context.IsAssignmentTarget=false;
+ this.Context.IsBindingElement=false;
+ let markers=[startToken,this.LookAhead];
+ let left=expr;
+ let right=this.IsolateCoverGrammar(this.ParseExponentiationExpression);
+ let stack=[left,token.Value,right];
+ let precedences = [prec];
+ while(true)
+ {
+ prec=this.BinaryPrecedence(this.LookAhead);
+ if (prec<=0) break;
+
+ while(stack.length>2 && prec<=precedences[precedences.length-1])
+ {
+ right=stack.pop();
+ let operator=stack.pop();
+ precedences.pop();
+ left=stack.pop();
+ markers.pop();
+ let node=this.StartNode(markers[markers.length - 1]);
+ stack.push(this.Finalize(node, this.Node.BinaryExpression(operator, left, right)));
+ }
+
+ //Shift
+ stack.push(this.NextToken().Value);
+ precedences.push(prec);
+ markers.push(this.LookAhead);
+ stack.push(this.IsolateCoverGrammar(this.ParseExponentiationExpression));
+ }
+
+ let i=stack.length-1;
+ expr=stack[i];
+ let lastMarker=markers.pop();
+ while(i>1)
+ {
+ let marker=markers.pop();
+ let lastLineStart=lastMarker && lastMarker.LineStart;
+ let node=this.StartNode(marker, lastLineStart);
+ let operator=stack[i-1];
+ expr=this.Finalize(node, this.Node.BinaryExpression(operator, stack[i - 2], expr));
+ i-=2;
+ lastMarker=marker;
+ }
+ }
+
+ return expr;
+ }
+
+ this.ParseExponentiationExpression=function()
+ {
+ let startToken=this.LookAhead;
+ let expr=this.InheritCoverGrammar(this.ParseUnaryExpression);
+
+ return expr;
+ }
+
+ this.ParseUnaryExpression=function()
+ {
+ let expr;
+ if (this.Match('+') || this.Match('-'))
+ {
+ let node=this.StartNode(this.LookAhead);
+ let token=this.NextToken();
+ expr=this.InheritCoverGrammar(this.ParseUnaryExpression);
+ expr=this.Finalize(node, this.Node.UnaryExpression(token.Value, expr));
+ this.Context.IsAssignmentTarget=false;
+ this.Context.IsBindingElement=false;
+ }
+ else
+ {
+ expr=this.ParseUpdateExpression();
+ }
+
+ return expr;
+ }
+
+ // https://tc39.github.io/ecma262/#sec-update-expressions
+ this.ParseUpdateExpression=function()
+ {
+ let expr;
+ let startToken=this.LookAhead;
+ expr=this.InheritCoverGrammar(this.ParseLeftHandSideExpressionAllowCall);
+
+ return expr;
+ }
+
+ this.ParseLeftHandSideExpressionAllowCall=function()
+ {
+ let startToken=this.LookAhead;
+ let expr;
+ expr=this.InheritCoverGrammar(this.ParsePrimaryExpression);
+
+ while(true)
+ {
+ if (this.Match('.'))
+ {
+ this.Context.IsBindingElement = false;
+ this.Context.IsAssignmentTarget = true;
+ this.Expect('.');
+ const property = this.ParseIdentifierName();
+ expr = this.Finalize(this.StartNode(startToken), this.Node.StaticMemberExpression(expr, property));
+ }
+ else if (this.Match('('))
+ {
+ this.Context.IsBindingElement=false;
+ this.Context.IsAssignmentTarget=false;
+ var args=this.ParseArguments(); //解析 调用参数
+ expr = this.Finalize(this.StartNode(startToken), this.Node.CallExpression(expr, args, startToken));
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ return expr;
+ }
+
+ /*
+ BooleanLiteral = 1,
+ EOF=2,
+ Identifier=3,
+ Keyword=4,
+ NullLiteral=5,
+ NumericLiteral=6,
+ Punctuator=7,
+ StringLiteral=9,
+ RegularExpression=9,
+ Template=10
+ */
+ this.IsIdentifierName = function (token)
+ {
+ return token.Type === 3 //Identifier
+ || token.Type === 4 //Keyword
+ || token.Type === 1 //BooleanLiteral
+ || token.Type === 5;//NullLiteral;
+ }
+
+ this.ParseIdentifierName = function ()
+ {
+ const node = this.CreateNode();
+ const token = this.NextToken();
+ if (!this.IsIdentifierName(token))
+ {
+ this.ThrowUnexpectedToken(token);
+ }
+
+ return this.Finalize(node, this.Node.Identifier(token.Value, token));
+ }
+
+ // https://tc39.github.io/ecma262/#sec-left-hand-side-expressions
+ this.ParseArguments=function()
+ {
+ this.Expect('(');
+ var args=[];
+ if (!this.Match(')'))
+ {
+ while(true)
+ {
+ let expr=this.IsolateCoverGrammar(this.ParseAssignmentExpression);
+ args.push(expr);
+
+ if (this.Match(')')) break;
+
+ this.ExpectCommaSeparator();
+
+ if (this.Match(')')) break;
+ }
+ }
+
+ this.Expect(')');
+ return args;
+ }
+
+ // Quietly expect a comma when in tolerant mode, otherwise delegates to expect().
+ this.ExpectCommaSeparator=function()
+ {
+ this.Expect(',');
+ }
+
+ // https://tc39.github.io/ecma262/#sec-primary-expression
+ this.ParsePrimaryExpression=function()
+ {
+ let node=this.CreateNode();
+ let expr;
+ var token, raw;
+ switch(this.LookAhead.Type)
+ {
+ case 3:/* Identifier */
+ token = this.NextToken();
+ expr = this.Finalize(node, this.Node.Identifier(token.Value, token));
+ break;
+ case 6:/* NumericLiteral */
+ case 8:/* StringLiteral */
+ this.Context.IsAssignmentTarget=false;
+ this.Context.IsBindingElement=false;
+ token=this.NextToken();
+ raw=this.GetTokenRaw(token);
+ expr=this.Finalize(node, this.Node.Literal(token.Value,raw));
+ break;
+ case 7:/* Punctuator */
+ switch(this.LookAhead.Value)
+ {
+ case '(':
+ this.Context.IsBindingElement=false;
+ expr=this.InheritCoverGrammar(this.ParseGroupExpression);
+ break;
+ default:
+ expr=this.ThrowUnexpectedToken(this.NextToken())
+ }
+ break;
+ default:
+ expr = this.ThrowUnexpectedToken(this.NextToken());
+ }
+
+ return expr;
+ }
+
+ this.ParseGroupExpression=function()
+ {
+ let expr;
+ this.Expect('(');
+ if (this.Match(')'))
+ {
+ this.NextToken();
+ }
+ else
+ {
+ let startToken=this.LookAhead;
+ let params=[];
+ let arrow=false;
+ this.Context.IsBindingElement=true;
+ expr=this.InheritCoverGrammar(this.ParseAssignmentExpression);
+ if (this.Match(','))
+ {
+ let expressions=[];
+ this.Context.IsAssignmentTarget=false;
+ expressions.push(expr);
+ while(this.LookAhead.Type!=2 /* EOF */)
+ {
+ if (!this.Match(',')) break;
+
+ this.NextToken();
+ if (this.Match(')'))
+ {
+
+ }
+ }
+ }
+
+ if (!arrow)
+ {
+ this.Expect(')');
+ this.Context.IsBindingElement=false;
+ }
+ }
+
+ return expr;
+ }
+
+ // https://tc39.github.io/ecma262/#sec-expression-statement
+ this.ParseExpressionStatement=function()
+ {
+ let node=this.CreateNode();
+ let expr=this.ParseExpression();
+ this.ConsumeSemicolon();
+
+ return this.Finalize(node,this.Node.ExpressionStatement(expr));
+ }
+
+ this.ConsumeSemicolon=function()
+ {
+ if (this.Match(';'))
+ {
+ this.NextToken();
+ }
+ else if (!this.HasLineTerminator)
+ {
+ //if (this.LookAhead.Type!=2/*EOF*/ && !this.Match('}'))
+
+ this.LastMarker.Index=this.StartMarker.Index;
+ this.LastMarker.Line=this.StartMarker.Line;
+ this.LastMarker.Column=this.StartMarker.Column;
+ }
+ }
+
+ this.ReinterpretExpressionAsPattern=function(expr)
+ {
+ switch(expr.Type)
+ {
+ case Syntax.Identifier:
+ case Syntax.MemberExpression:
+ case Syntax.AssignmentExpression:
+ break;
+ default:
+ break;
+ }
+ }
+
+ this.Finalize=function(marker,node)
+ {
+ node.Marker={ Line:marker.Line, Column:marker.Column, Index:marker.Index };
+ return node;
+ }
+
+ this.BinaryPrecedence = function (token)
+ {
+ let op = token.Value;
+ let precedence;
+
+ if (token.Type === 7 /* Punctuator */) precedence = this.PeratorPrecedence[op] || 0;
+ else precedence = 0;
+
+ return precedence;
+ };
+
+ this.IsolateCoverGrammar=function(parseFunction)
+ {
+ let previousIsBindingElement=this.Context.IsBindingElement;
+ let previousIsAssignmentTarget=this.Context.IsAssignmentTarget;
+ let previousFirstCoverInitializedNameError=this.Context.FirstCoverInitializedNameError;
+
+ this.Context.IsBindingElement=true;
+ this.Context.IsAssignmentTarget=true;
+ this.Context.FirstCoverInitializedNameError=null;
+ let result=parseFunction.call(this);
+
+ if (this.Context.FirstCoverInitializedNameError!=null)
+ {
+ //错误 this.throwUnexpectedToken(this.context.firstCoverInitializedNameError);
+ }
+
+ this.Context.IsBindingElement=previousIsBindingElement;
+ this.Context.IsAssignmentTarget=previousIsAssignmentTarget;
+ this.Context.FirstCoverInitializedNameError=previousFirstCoverInitializedNameError;
+
+ return result;
+ }
+
+ this.InheritCoverGrammar = function (parseFunction)
+ {
+ let previousIsBindingElement = this.Context.IsBindingElement;
+ let previousIsAssignmentTarget = this.Context.IsAssignmentTarget;
+ let previousFirstCoverInitializedNameError = this.Context.FirstCoverInitializedNameError;
+ this.Context.IsBindingElement = true;
+ this.Context.IsAssignmentTarget = true;
+ this.Context.FirstCoverInitializedNameError = null;
+
+ let result = parseFunction.call(this);
+
+ this.Context.IsBindingElement = this.Context.IsBindingElement && previousIsBindingElement;
+ this.Context.IsAssignmentTarget = this.Context.IsAssignmentTarget && previousIsAssignmentTarget;
+ this.Context.FirstCoverInitializedNameError = previousFirstCoverInitializedNameError || this.Context.FirstCoverInitializedNameError;
+
+ return result;
+ };
+
+ this.ThrowUnexpectedToken=function(token,message)
+ {
+ throw this.UnexpectedTokenError(token,message);
+ }
+
+ this.ThrowUnexpectedError=function(index,line,column,message)
+ {
+ let msg=message || "执行异常";
+
+ return this.ErrorHandler.ThrowError(index,line,column,msg);
+ }
+
+ this.UnexpectedTokenError=function(token,message)
+ {
+ let msg=message || Messages.UnexpectedToken;
+ let value='ILLEGAL';
+ if (token)
+ {
+ if (!message)
+ {
+
+ }
+ value=token.Value;
+ }
+
+ msg=msg.replace("%0",value);
+ if (token && typeof(token.LineNumber)=='number')
+ {
+ let index=token.Start;
+ let line=token.LineNumber;
+ let lastMarkerLineStart=this.LastMarker.Index-this.LastMarker.Column;
+ let column=token.Start-lastMarkerLineStart+1;
+ return this.ErrorHandler.CreateError(index,line,column,msg);
+ }
+ else
+ {
+ let index=this.LastMarker.Index;
+ let line=this.LastMarker.Line;
+ let column=this.LastMarker.Column+1;
+ return this.ErrorHandler.CreateError(index,line,column,msg);
+ }
+ }
+}
+
+
+/*
+ 算法类
+*/
+function JSAlgorithm(errorHandler, symbolData)
+{
+ this.ErrorHandler=errorHandler;
+ this.SymbolData = symbolData; //股票数据
+
+ //相加
+ this.Add=function(data,data2)
+ {
+ let isNumber=typeof(data)=='number';
+ let isNumber2=typeof(data2)=='number';
+
+ //单数值相加
+ if (isNumber && isNumber2) return data+data2;
+
+ //都是数组相加
+ let result=[];
+ if (!isNumber && !isNumber2)
+ {
+ let count=Math.max(data.length, data2.length);
+ for(let i=0;idata2 ? 1 : 0);
+
+ //都是数组比较
+ let result=[];
+ if (!isNumber && !isNumber2)
+ {
+ let count=Math.max(data.length, data2.length);
+ for(let i=0;idata2[i] ? 1:0);
+ }
+ }
+
+ return result;
+ }
+
+ if (isNumber) //单数据-数组
+ {
+ for(let i in data2)
+ {
+ result[i]=null;
+ if ( !isNaN(data) && !isNaN(data2[i]) ) result[i]=(data>data2[i] ? 1 : 0);
+ }
+ }
+ else //数组-单数据
+ {
+ for(let i in data)
+ {
+ result[i]=null;
+ if ( !isNaN(data[i]) && !isNaN(data2) ) result[i]=(data[i]>data2 ? 1 : 0);
+ }
+ }
+
+ return result;
+ }
+
+ //大于等于
+ this.GTE=function(data,data2)
+ {
+ let isNumber=typeof(data)=='number';
+ let isNumber2=typeof(data2)=='number';
+
+ //单数值比较
+ if (isNumber && isNumber2) return (data>=data2 ? 1 : 0);
+
+ //都是数组比较
+ let result=[];
+ if (!isNumber && !isNumber2)
+ {
+ let count=Math.max(data.length, data2.length);
+ for(let i=0;i=data2[i] ? 1:0);
+ }
+ }
+
+ return result;
+ }
+
+ if (isNumber) //单数据-数组
+ {
+ for(let i in data2)
+ {
+ result[i]=null;
+ if ( !isNaN(data) && !isNaN(data2[i]) ) result[i]=(data>=data2[i] ? 1 : 0);
+ }
+ }
+ else //数组-单数据
+ {
+ for(let i in data)
+ {
+ result[i]=null;
+ if ( !isNaN(data[i]) && !isNaN(data2) ) result[i]=(data[i]>=data2 ? 1 : 0);
+ }
+ }
+
+ return result;
+ }
+
+ //小于
+ this.LT=function(data,data2)
+ {
+ let isNumber=typeof(data)=='number';
+ let isNumber2=typeof(data2)=='number';
+
+ //单数值比较
+ if (isNumber && isNumber2) return (data=data2 ? 1 : 0);
+
+ //都是数组比较
+ let result=[];
+ if (!isNumber && !isNumber2)
+ {
+ let count=Math.max(data.length, data2.length);
+ for(let i=0;iOPEN,HIGH,LOW)表示该周期收阴则返回最高值,否则返回最低值
+ */
+ this.IFN=function(data,trueData,falseData)
+ {
+ return this.IF(data,falseData,trueData);
+ }
+
+ //指标函数 函数名全部大写
+ this.REF=function(data,n)
+ {
+ let result=[];
+ if (typeof(n)=='number')
+ {
+ if (data.length<=0) return result;
+ if (n>=data.length) return result;
+
+ result=data.slice(0,data.length-n);
+
+ for(let i=0;i=n.length) continue;
+ var value=n[i];
+ if (value>0 && value<=i) result[i]=data[i-value];
+ else if (i) result[i]=result[i-1];
+ else result[i]=data[i];
+ }
+ }
+
+ return result;
+ }
+
+ //引用若干周期前的数据(未作平滑处理).
+ //用法: REFV(X,A),引用A周期前的X值.A可以是变量.
+ //平滑处理:当引用不到数据时进行的操作.
+ //例如: REFV(CLOSE,BARSCOUNT(C)-1)表示第二根K线的收盘价.
+ this.REFV=function(data,n)
+ {
+ let result=[];
+ if (typeof(n)=='number')
+ {
+ if (data.length<=0) return result;
+ if (n>=data.length) return result;
+
+ result=data.slice(0,data.length-n);
+
+ for(let i=0;i=n.length) continue;
+ var value=n[i];
+ if (value>=0 && value<=i) result[i]=data[i-value];
+ }
+ }
+
+ return result;
+ }
+
+ //属于未来函数,引用若干周期后的数据(平滑处理).
+ //用法: REFX(X,A),引用A周期后的X值.A可以是变量.
+ //平滑处理:当引用不到数据时进行的操作.此函数中,平滑时使用上一个周期的引用值.
+ //例如: TT:=IF(C>O,1,2);
+ // REFX(CLOSE,TT);表示阳线引用下一周期的收盘价,阴线引用日后第二周期的收盘价.
+ this.REFX=function(data,n)
+ {
+ let result=[];
+ if (typeof(n)=='number')
+ {
+ if (data.length<=0) return result;
+ if (n>=data.length) return result;
+
+ result=data.slice(n,data.length);
+
+ //平滑处理
+ var lastData=data[data.length-1];
+ for(let i=0;i=n.length) continue;
+ var value=n[i];
+ if (value>=0 && value+i=data.length) return result;
+
+ result=data.slice(n,data.length);
+
+ //平滑处理
+ for(let i=0;i=n.length) continue;
+ var value=n[i];
+ if (value>=0 && value+i= 0; --j)
+ {
+ var value = data[i - j];
+ if (!this.IsNumber(value))
+ {
+ value = preValue; //空数据就取上一个数据
+ data[i - j] = value;
+ }
+ else
+ {
+ preValue = value;
+ }
+ sum += value;
+ }
+
+ result[i] = sum / dayCount;
+ }
+
+ return result;
+ }
+
+ //指数平均数指标 EMA(close,10)
+ this.EMA=function(data,dayCount)
+ {
+ var result = [];
+
+ var offset=0;
+ if (offset>=data.length) return result;
+
+ //取首个有效数据
+ for(;offset= 0 && j < data.length)
+ {
+ if (this.IsNumber(data[j]))
+ {
+ sum += data[j];
+ ++count;
+ }
+ }
+ }
+
+ if (count != 0) result[i] = (sum / count);
+ else result[i] = null;
+
+ sum = 0;
+ count = 0;
+ }
+
+ return result;
+ }
+
+ /*
+ SMA 移动平均
+ 返回移动平均。
+ 用法: SMA(X,N,M) X的M日移动平均,M为权重,如Y=(X*M+Y'*(N-M))/N
+ */
+ this.SMA=function(data,n,m)
+ {
+ var result = [];
+
+ var i=0;
+ var lastData=null;
+ for(;i= 0; --j)
+ {
+ var value = data[i - j];
+ if (!this.IsNumber(value))
+ {
+ value = preValue;
+ data[i - j] = value;
+ }
+ else
+ preValue = value;
+
+ count += dayCount - j;
+ sum += value * (dayCount - j);
+ }
+ result[i] = sum / count;
+ }
+ return result;
+ }
+
+ /*
+ 返回平滑移动平均
+ 用法:MEMA(X,N):X的N日平滑移动平均,如Y=(X+Y'*(N-1))/N
+ MEMA(X,N)相当于SMA(X,N,1)
+ */
+ this.MEMA = function (data, dayCount)
+ {
+ let result = [];
+ if (!data || !data.length) return result;
+ var i = 0, j = 0;
+ for (j = 0; j < data.length && !this.IsNumber(data[j]); ++j)
+ {
+ result[j] = null;
+ }
+ i = j;
+ if (dayCount < 1 || i + dayCount >= data.length) return result;
+ var sum = 0;
+ var data = data.slice(0);
+ for (; i < j + dayCount; ++i)
+ {
+ result[i] = null;
+ if (!this.IsNumber(data[i]) && i - 1 >= 0)
+ data[i] = data[i - 1];
+ sum += data[i];
+ }
+ result[i - 1] = sum / dayCount;
+ for (; i < data.length; ++i)
+ {
+ if (this.IsNumber(result[i - 1]) && this.IsNumber(data[i]))
+ result[i] = (data[i] + result[i - 1] * (dayCount - 1)) / dayCount;
+ else if (i - 1 > -1 && this.IsNumber(result[i - 1]))
+ result[i] = result[i - 1];
+ else
+ result[i] = null;
+ }
+ return result;
+ }
+
+ /*
+ 加权移动平均
+ 返回加权移动平均
+ 用法:EXPMA(X,M):X的M日加权移动平均
+ EXPMA[i]=buffer[i]*para+(1-para)*EXPMA[i-1] para=2/(1+__para)
+ */
+ this.EXPMA=function(data,dayCount)
+ {
+ let result=[];
+ if (dayCount>=data.length) return result;
+
+ let i=dayCount;
+ for(;i=data.length) return result;
+
+ var index=0;
+ for(;index= start; --i)
+ {
+ for (j = i, total = 0; j >= start && total < data2[i]; --j)
+ total += data[j];
+ if (j < start) result[i] = null;
+ else result[i] = i - j;
+ }
+ for (i = start + 1; i < data.length; ++i)
+ {
+ if (result[i] == null)
+ result[i] = result[i - 1];
+ }
+ return result;
+ }
+
+ /*
+ 求相反数.
+ 用法:REVERSE(X)返回-X.
+ 例如:REVERSE(CLOSE)返回-CLOSE
+ */
+ this.REVERSE = function (data)
+ {
+ var result = [];
+ var i = 0;
+ for (; i < data.length && !this.isNumber(data[i]); ++i)
+ {
+ result[i] = null;
+ }
+ for (; i < data.length; ++i)
+ {
+ if (!this.isNumber(data[i]))
+ result[i] = null;
+ else
+ result[i] = 0 - data[i];
+ }
+ return result;
+ }
+
+ this.COUNT=function(data,n)
+ {
+ if (Array.isArray(n))
+ {
+ var start=null;
+ var dataCount=data.length;
+ for(var i=0;i=0 && k= n.length) continue;
+
+ max = null;
+ var count = n[i];
+ if (count > 0 && count <= i)
+ {
+ for (j = i - count; j <= i; ++j)
+ {
+ if (max == null || max < data[j]) max = data[j];
+ }
+ }
+ else
+ {
+ count = i;
+ for (j = 0; j <= i; ++j)
+ {
+ if (max == null || max < data[j]) max = data[j];
+ }
+ }
+
+ result[i] = max;
+ }
+ }
+ else
+ {
+ if (n > data.length) return result;
+ if (n <= 0) n = data.length - 1;
+
+ var nMax = 0;
+ for (nMax = 0; nMax < data.length; ++nMax)
+ {
+ if (this.IsNumber(data[nMax])) break;
+ }
+
+ if (nMax < data.length) result[nMax] = data[nMax];
+ for (var i = nMax + 1, j = 2; i < data.length && j < n; ++i, ++j)
+ {
+ if (data[i] >= data[nMax]) nMax = i;
+ result[i] = data[nMax];
+ }
+
+ for (; i < data.length; ++i)
+ {
+ if (i - nMax < n)
+ {
+ nMax = data[i] < data[nMax] ? nMax : i;
+ }
+ else
+ {
+ for (j = nMax = (i - n + 1); j <= i; ++j)
+ {
+ nMax = data[j] < data[nMax] ? nMax : j;
+ }
+ }
+
+ result[i] = data[nMax];
+ }
+ }
+
+ return result;
+ }
+
+ /*
+ LLV 最低值
+ 求最低值。
+ 用法: LLV(X,N) 求N周期内X最低值,N=0则从第一个有效值开始。
+ 例如: LLV(LOW,0) 表示求历史最低价。
+ */
+ this.LLV=function(data,n)
+ {
+ var result = [];
+ if (Array.isArray(n))
+ {
+ for (var i = 0; i < data.length; ++i)
+ {
+ result[i] = null;
+ if (i >= n.length) continue;
+
+ var min = null;
+ var count = n[i];
+ if (count > 0 && count <= i)
+ {
+ for (var j = i - count; j <= i; ++j)
+ {
+ if (min == null || min > data[j]) min = data[j];
+ }
+ }
+ else
+ {
+ count = i;
+ for (var j = 0; j <= i; ++j)
+ {
+ if (min == null || min > data[j]) min = data[j];
+ }
+ }
+
+ result[i] = min;
+ }
+ }
+ else
+ {
+ if (n>data.length) return result;
+ if (n<=0) n=data.length-1;
+
+ var nMin=0;
+ for(nMin=0;nMindata[nMin]?nMin:i;
+ }
+ else
+ {
+ for(j=nMin=(i-n+1);j<=i;++j)
+ {
+ nMin=data[j]>data[nMin]?nMin:j;
+ }
+ }
+
+ result[i]=data[nMin];
+ }
+ }
+
+ return result;
+ }
+
+ this.STD=function(data,n)
+ {
+ var result=[];
+
+ var total=0;
+ var averageData=[]; //平均值
+ for(var i=n-1;i data2[index] && data[index - 1] < data2[index - 1]) ? 1 : 0;
+ }
+ }
+ else if (Array.isArray(data) && typeof (data2) == 'number')
+ {
+ var index = 0;
+ for (; index < data.length; ++index)
+ {
+ if (this.IsNumber(data[index])) break;
+ }
+
+ for (++index; index < data.length; ++index)
+ {
+ result[index] = (data[index] > data2 && data[index - 1] < data2) ? 1 : 0;
+ }
+ }
+ else if (typeof (data) == 'number' && Array.isArray(data2))
+ {
+ var index = 0;
+ for (; index < data2.length; ++index)
+ {
+ if (this.IsNumber(data2[index])) break;
+ }
+
+ for (++index; index < data2.length; ++index)
+ {
+ result[index] = (data2[index] < data && data2[index - 1] > data) ? 1 : 0;
+ }
+ }
+
+ return result;
+ }
+
+ //累乘
+ this.MULAR=function(data,n)
+ {
+ var result=[];
+ if(data.lengthdatanum) return result;
+ for(E=0; i < datanum && j < num; ++i,++j)
+ E += data[i]/num;
+ if (j == num)
+ {
+ DEV = 0;
+ for(i--; k < num; k++)
+ DEV += (data[i-k]-E) * (data[i-k]-E);
+ result[i] = DEV;
+ i++;
+ }
+ for(; i < datanum; ++i)
+ {
+ E += (data[i] - data[i-num]) / num;
+ for(DEV=0, k = 0; k < num; ++k)
+ DEV += (data[i-k]-E) * (data[i-k]-E);
+ result[i] = DEV;
+ }
+ return result;
+ }
+
+ //NOT 取反
+ //求逻辑非。
+ //用法: NOT(X) 返回非X,即当X=0时返回1,否则返回0。
+ //例如: NOT(ISUP) 表示平盘或收阴。
+ this.NOT=function(data)
+ {
+ let isNumber=typeof(data)=='number';
+ if (isNumber) return data? 0:1;
+
+ let result=[];
+ for(let i in data)
+ {
+ result[i]=null;
+ if (this.IsNumber(data[i])) result[i]=data[i]?0:1;
+ }
+
+ return result;
+ }
+
+ //FORCAST 线性回归预测值
+ //FORCAST(X,N) 返回线性回归预测值。
+ this.FORCAST=function(data,n)
+ {
+ var result=[];
+ if (typeof(n)!='number') n=parseInt(n); //字符串的转成数值型
+ var num = n;
+ var datanum = data.length;
+ if (num < 1 || num >= datanum)
+ return result;
+ var Ex = 0, Ey = 0, Sxy = 0, Sxx = 0, Const, Slope;
+ var i, j,x;
+ for(j = 0; j < datanum && !this.IsNumber(data[j]); ++j)
+ {
+ result[j] = null;
+ }
+ for(i = j+num-1; i < datanum; ++i)
+ {
+ Ex = Ey = Sxy = Sxx = 0;
+ for (j = 0, x = num; j < num && j <= i; ++j,--x)
+ {
+ Ex +=x;
+ Ey += data[i - j];
+ }
+ Ex /= num;
+ Ey /= num;
+ for (j = 0, x = num; j < num && j <= i; ++j, --x)
+ {
+ Sxy += (x-Ex)*(data[i-j]-Ey);
+ Sxx += (x-Ex)*(x-Ex);
+ }
+ Slope = Sxy / Sxx;
+ Const = Ey - Ex*Slope;
+ result[i] = Slope * num + Const;
+ }
+
+ return result;
+ }
+
+ //SLOPE 线性回归斜率
+ //SLOPE(X,N) 返回线性回归斜率。
+ this.SLOPE=function(data,n)
+ {
+ let result=[];
+ if (typeof(n)!='number') n=parseInt(n); //字符串的转成数值型
+ if (n<1 || !data.length) return result;
+ if (n>=data.length) return result;
+
+ let start=0;
+ for(let i=0;i= datanum)
+ return result;
+ var i = 0, j = 0;
+ for(i = 0; i < datanum && !this.isNumber(data[i]); ++i)
+ {
+ result[i] = null;
+ }
+ var SigmaPowerX = 0, SigmaX = 0, MidResult;
+ for (; i < datanum && j < num; ++i, ++j)
+ {
+ SigmaPowerX += data[i] * data[i];
+ SigmaX += data[i];
+ }
+ if (j == num)
+ {
+ MidResult = num*SigmaPowerX - SigmaX*SigmaX;
+ result[i-1] = Math.sqrt(MidResult) / num;
+ }
+ for(; i < datanum; ++i)
+ {
+ SigmaPowerX += data[i]*data[i] - data[i-num]*data[i-num];
+ SigmaX += data[i] - data[i-num];
+ MidResult = num*SigmaPowerX - SigmaX*SigmaX;
+ result[i] = Math.sqrt(MidResult) / num;
+ }
+ }
+
+ //VAR 估算样本方差
+ //VAR(X,N) 返回估算样本方差。
+ this.VAR=function(data,n)
+ {
+ var result=[];
+ if (typeof(n)!='number') n=parseInt(n); //字符串的转成数值型
+ var num = n;
+ var datanum = data.length;
+ if (num <= 1 || num >= datanum)
+ return result;
+ var i, j;
+ for (i = 0; i < datanum && !this.IsNumber(data[i]); ++i)
+ {
+ result[i] = null;
+ }
+ var SigmaPowerX, SigmaX;
+ for (j = 0, i = i+num-1; i < datanum; ++i)
+ {
+ SigmaPowerX = SigmaX = 0;
+ for(j=0; j < num && j <= i; ++j)
+ {
+ SigmaPowerX += data[i-j] * data[i-j];
+ SigmaX += data[i-j];
+ }
+ result[i] = (num*SigmaPowerX - SigmaX*SigmaX) / num * (num -1);
+ }
+
+ return result;
+ }
+
+ //VARP 总体样本方差
+ //VARP(X,N) 返回总体样本方差 。
+ this.VARP=function(data,n)
+ {
+ var result=[];
+ if (typeof(n)!='number') n=parseInt(n); //字符串的转成数值型
+ var num = n;
+ var datanum = data.length;
+ if (num < 1 || num >= datanum)
+ return result;
+ var i = 0, j = 0;
+ for (i = 0; i < datanum && !this.IsNumber(data[i]); ++i)
+ {
+ result[i] = null;
+ }
+ var SigmaPowerX = 0, SigmaX = 0;
+ for (; i < datanum && j < num; ++i, ++j)
+ {
+ SigmaPowerX += data[i] * data[i];
+ SigmaX += data[i];
+ }
+ if (j == num)
+ result[i-1] = (num*SigmaPowerX - SigmaX*SigmaX) / (num*num);
+ for(; i < datanum; ++i)
+ {
+ SigmaPowerX += data[i]*data[i] - data[i-num]*data[i-num];
+ SigmaX += data[i] - data[i-num];
+ result[i] = (num*SigmaPowerX - SigmaX*SigmaX) / (num*num);
+ }
+
+ return result;
+ }
+
+ //RANGE(A,B,C)表示A>B AND AMath.min(range,range2) && data=range.length) continue;
+
+ rangeValue=range[i];
+ }
+ else
+ {
+ rangeValue=range;
+ }
+ if (!this.IsNumber(rangeValue)) continue;
+
+ if (!isNumber3)
+ {
+ if (i>=range2.length) continue;
+
+ rangeValue2=range2[i];
+ }
+ else
+ {
+ rangeValue2=range2;
+ }
+ if (!this.IsNumber(rangeValue2)) continue;
+
+
+ result[i]= (value>Math.min(rangeValue,rangeValue2) && value0) latestID==i;
+
+ if (i-latestIDOPEN,5)查找阳线,5天内再次出现的阳线不被记录在内
+ */
+ this.FILTER = function (data, n)
+ {
+ var result = [];
+ for (let i = 0, j = 0; i < data.length; ++i)
+ {
+ if (data[i])
+ {
+ result[i] = 1;
+ for (j = 0; j < n && j + i + 1 < data.length; ++j)
+ {
+ result[j + i + 1] = 0;
+ }
+ i += n;
+ }
+ else
+ {
+ result[i] = 0;
+ }
+ }
+
+ return result;
+ }
+
+ this.BARSLAST=function(data)
+ {
+ var result=[];
+ if (!data) return result;
+
+ let day=null;
+ for(let i=0;i0) day=0;
+ else if (day!=null) ++day;
+
+ if (day!=null) result[i]=day;
+ }
+
+ return result;
+ }
+
+ /*
+ N周期内第一个条件成立到当前的周期数.
+ 用法:
+ BARSSINCEN(X,N):N周期内第一次X不为0到现在的天数,N为常量
+ 例如:
+ BARSSINCEN(HIGH>10,10)表示10个周期内股价超过10元时到当前的周期数
+ */
+ this.BARSSINCEN = function (data, n)
+ {
+ var result=[];
+ if (this.IsNumber(n) && Array.isArray(data))
+ {
+ var nPeriod=n;
+ if (nPeriod<1) nPeriod=data.length;
+ var i=this.GetFirstVaildIndex(data);
+ if (i>=data.length) return result;
+ var j=0;
+ if (i <= nPeriod - 1) j = nPeriod - 1;
+ else j = i;
+
+ result[j] = j - i;
+
+ for (; j < data.length; ++j)
+ {
+ if (this.IsNumber(result[j - 1]))
+ {
+ if (result[j - 1] + 1 < nPeriod)
+ {
+ result[j] = result[j - 1] + 1;
+ }
+ else
+ {
+ for (var k = j - nPeriod+1; k <= j; ++k)
+ {
+ if (!(Math.abs(data[k]) < 0.000001))
+ {
+ result[j] = j - k;
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (!(Math.abs(data[j]) < 0.000001))
+ result[j] = 0;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ /*
+ 第一个条件成立到当前的周期数.
+ 用法:
+ BARSSINCE(X):第一次X不为0到现在的天数
+ 例如:
+ BARSSINCE(HIGH>10)表示股价超过10元时到当前的周期数
+ */
+ this.BARSSINCE = function (data)
+ {
+ var result = [];
+ var day = null;
+
+ for (let i = 0; i < data.length; ++i)
+ {
+ result[i] = null;
+ if (day == null)
+ {
+ if (data[i]) day = 0;
+ }
+ else
+ {
+ ++day;
+ }
+
+ if (day) result[i] = day;
+ }
+
+ return result;
+ }
+
+ /*三角函数调用 func 三角函数
+ 反正切值. 用法: ATAN(X)返回X的反正切值
+ 余弦值. 用法: COS(X)返回X的余弦值
+ 正弦值. 用法: SIN(X)返回X的正弦值
+ 正切值. 用法: TAN(X)返回X的正切值
+
+ 求自然对数. 用法: LN(X)以e为底的对数 例如: LN(CLOSE)求收盘价的对数
+ 求10为底的对数. 用法: LOG(X)取得X的对数 例如: LOG(100)等于2
+ 指数. 用法: EXP(X)为e的X次幂 例如: EXP(CLOSE)返回e的CLOSE次幂
+ 开平方. 用法: SQRT(X)为X的平方根 例如: SQRT(CLOSE)收盘价的平方根
+ */
+ this.Trigonometric = function (data, func)
+ {
+ if (!Array.isArray(data))
+ {
+ if (this.IsNumber(data)) return func(data);
+
+ return null;
+ }
+ else
+ {
+ var result = [];
+ for (let i in data)
+ {
+ var item = data[i];
+ if (this.IsNumber(item)) result[i] = func(item);
+ else result[i] = null;
+ }
+
+ return result;
+ }
+ }
+
+ //反正弦值. 用法: ASIN(X)返回X的反正弦值
+ this.ASIN = function (data)
+ {
+ if (!Array.isArray(data))
+ {
+ if (this.IsNumber(data)) return Math.acos(data);
+ return null;
+ }
+ else
+ {
+ var result = [];
+ for (let i in data)
+ {
+ var item = data[i];
+ result[i] = null;
+ if (this.IsNumber(item))
+ {
+ if (item >= -1 && item <= 1)
+ {
+ result[i] = Math.asin(item);
+ }
+ else if (i - 1 >= 0)
+ {
+ var preItem = result[i - 1];
+ if (this.IsNumber(preItem)) result[i] = preItem;
+ }
+ }
+ }
+
+ return result;
+ }
+ }
+
+
+ //反余弦值. 用法: ACOS(X)返回X的反余弦值
+ this.ACOS = function (data)
+ {
+ if (!Array.isArray(data))
+ {
+ if (this.IsNumber(data)) return Math.acos(data);
+
+ return null;
+ }
+ else
+ {
+ var result = [];
+ for (let i in data)
+ {
+ var item = data[i];
+ result[i] = null;
+ if (this.IsNumber(item))
+ {
+ if (item >= -1 && item <= 1)
+ {
+ result[i] = Math.acos(item);
+ }
+ else if (i - 1 >= 0) //超出范围使用上一个数值
+ {
+ var preItem = result[i - 1];
+ if (this.IsNumber(preItem)) result[i] = preItem;
+ }
+ }
+ }
+
+ return result;
+ }
+ }
+
+ /*
+ LAST(X,A,B):持续存在.
+ 用法:
+ LAST(CLOSE>OPEN,10,5)
+ 表示从前10日到前5日内一直阳线
+ 若A为0,表示从第一天开始,B为0,表示到最后日止
+ */
+ this.LAST = function (data, n, n2)
+ {
+ var result = [];
+ if (n2 <= 0) n2 = data.length - 1;
+ if (n2 > n) return result;
+
+ var day = 0;
+
+ for (let i = 0, j = 0; i < data.length; ++i) {
+ result[i] = 0;
+ day = 0;
+ var start = i - n;
+ var end = i - n2;
+ if (start < 0 || end < 0) continue;
+
+ for (j = start; j < data.length && j <= end; ++j, ++day) {
+ if (!data[j]) break;
+ }
+
+ if (day == end - start + 1) //[start,end]
+ result[i] = 1;
+ }
+
+ return result;
+ }
+
+ /*
+ 属于未来函数,之字转向.
+ 用法: ZIG(K,N),当价格变化量超过N%时转向,K表示0:开盘价,1:最高价,2:最低价,3:收盘价,其余:数组信息
+ 例如: ZIG(3,5)表示收盘价的5%的ZIG转向
+ */
+ this.ZIG=function(data,n)
+ {
+ var hisData=this.SymbolData.Data;
+ var result=[];
+ if (typeof(data)=='number')
+ {
+ switch(data)
+ {
+ case 0:
+ data=hisData.GetOpen();
+ break;
+ case 1:
+ data=hisData.GetHigh();
+ break;
+ case 2:
+ data=hisData.GetLow();
+ break;
+ case 3:
+ data=hisData.GetClose();
+ break;
+ default:
+ return result;
+ }
+ }
+
+ return this.ZIG_Calculate(data,n);
+ }
+
+ this.ZIG_Calculate=function(data,dRate)
+ {
+ var dest=[];
+ var nDataCount=data.length;
+ var m=this.GetFirstVaildIndex(data);
+ var i = 0, lLastPos = 0, lState = 0, j = 0;
+ var dif = 0;
+ for (i = m + 1, lLastPos = lState = m; i= dRate*data[m] ? (data[i]>data[m] ? i : -i) : m;
+ }
+
+ for (; i= data[i - 1] && data[i] >= data[i + 1])
+ {
+ if (lState<0)
+ {
+ if ((data[i] - data[-lState]) * 100= lLastPos; j--)
+ dest[j]=data[-lState] + (-lState - j)*dif;
+ lLastPos = -lState;
+ lState = i;
+ }
+ }
+ else if (data[i]>data[lState]) lState = i;
+ }
+ else if (data[i] <= data[i - 1] && data[i] <= data[i + 1])
+ {
+ if (lState>0)
+ {
+ if ((data[lState] - data[i]) * 100= nDataCount - 2)
+ {
+ if (lState>0 && data[nDataCount - 1] >= data[lState]) lState = nDataCount - 1;
+ if (lState<0 && data[nDataCount - 1] <= data[-lState]) lState = 1 - nDataCount;
+ }
+
+ if (lState>0)
+ {
+ dif = (data[lState] - data[j = lLastPos]) / (lState - lLastPos );
+ dest[j++]=data[lLastPos];
+ for (; j <= lState; ++j)
+ dest[j]=data[lLastPos] + (j - lLastPos)*dif;
+ }
+ else
+ {
+ dif = (data[lLastPos] - data[j = -lState]) / (-lState - lLastPos);
+ dest[j--]=data[-lState];
+ for (; j >= lLastPos; j--)
+ dest[j]=(data[-lState] + (-lState - j)*dif);
+ }
+ if ((lState = Math.abs(lState))= data[lState])
+ {
+ dif = (data[nDataCount - 1] - data[j = lState]) / (nDataCount - lState);
+ dest[j++]=(data[lState]);
+ for (; j= lState; j--)
+ dest[j]=(data[nDataCount - 1] + (nDataCount - j)*dif);
+ }
+ }
+
+ return dest;
+ }
+
+
+ this.GetFirstVaildIndex=function(data)
+ {
+ for (var i = 0; i subItem) findData = { ID: i, Value: subItem };
+ }
+ }
+
+ secondData.Value = findData.Value;
+ secondData.ID = findData.ID;
+
+ var lineCache = { Start: { ID: firstData.ID, Value: firstData.Value }, End: { ID: secondData.ID, Value: secondData.Value } };
+ var lineData = this.JSDraw.CalculateDrawLine(lineCache);//计算2个点的线上 其他点的数值
+ for (var i in lineData)
+ {
+ var lineItem = lineData[i];
+ result[lineItem.ID] = lineItem.Value;
+ }
+
+ if (thridData.ID == data.length - 1) //最后一组数据
+ {
+ //最后2个点的数据连成线
+ lineCache = { Start: { ID: secondData.ID, Value: secondData.Value }, End: { ID: thridData.ID, Value: thridData.Value } };
+ lineData = this.JSDraw.CalculateDrawLine(lineCache);//计算2个点的线上 其他点的数值
+ for (var i in lineData)
+ {
+ var lineItem = lineData[i];
+ result[lineItem.ID] = lineItem.Value;
+ }
+ }
+ else
+ {
+ firstData.ID = secondData.ID;
+ firstData.Value = secondData.Value;
+
+ secondData.ID = thridData.ID;
+ secondData.Value = thridData.Value;
+ secondData.Up = firstData.Value < secondData.Value;
+ }
+ }
+
+ /*
+ 属于未来函数,前M个ZIG转向波谷到当前距离.
+ 用法:
+ TROUGHBARS(K,N,M)表示之字转向ZIG(K,N)的前M个波谷到当前的周期数,M必须大于等于1
+ 例如:
+ TROUGHBARS(2,5,2)表示%5最低价ZIG转向的前2个波谷到当前的周期数
+ */
+ this.TROUGHBARS=function(data,n,n2)
+ {
+ var zigData=this.ZIG(data,n); //计算ZIG
+ var dest=[];
+
+ var lEnd =n2;
+ if (lEnd<1) return dest;
+
+ var nDataCount = zigData.length;
+ var trough = [];
+ for(var i=0;izigData[i - 1]; ++i);
+
+ for (; izigData[i-1]; ++i);
+
+ for(; izigData[i - 1]; ++i);
+
+ for (peak[0] = --i; izigData[i + 1])
+ {
+ if (lFlag)
+ {
+ if (lEnd)
+ {
+ var tempPeak=peak.slice(0);
+ for(var j=0;jzigData[i - 1]; ++i);
+
+ for (peak[0] = --i; izigData[i + 1])
+ {
+ if (lFlag)
+ {
+ if (lEnd)
+ {
+ var tempPeak=peak.slice(0);
+ for(var j=0;jOPEN,N)
+ 表示N日内一直阳线(N应大于0,小于总周期数,N支持变量)
+ */
+ this.EVERY = function (data, n)
+ {
+ var result = [];
+ if (n < 1) return result;
+ var i = 0;
+ for (; i < data.length; ++i)
+ {
+ result[i] = null;
+ if (this.IsNumber(data[i])) break;
+ }
+
+ var flag = 0;
+ for (; i < data.length; ++i)
+ {
+ if (data[i]) flag += 1;
+ else flag = 0;
+
+ if (flag == n)
+ {
+ result[i] = 1;
+ --flag;
+ }
+ else
+ {
+ result[i] = 0;
+ }
+ }
+
+ return result;
+ }
+
+ /*
+ 成本分布情况.
+ 用法:
+ COST(10),表示10%获利盘的价格是多少,即有10%的持仓量在该价格以下,其余90%在该价格以上,为套牢盘
+ 该函数仅对日线分析周期有效
+ */
+ this.COST = function (data, node)
+ {
+ var result=[];
+ var rate=data/100;
+ if(rate<0.000001 || rate>1) return result;
+
+ var kData=this.SymbolData.Data.Data;
+ if (!kData || kData.length<=0) return result;
+ var aryCapital=this.SymbolData.GetStockCacheData({ FunctionName:"FINANCE", Args:[7], ArgCount:1, Node:node } ); //流通股本
+
+ var dMaxPrice=kData[0].High,dMinPrice=kData[0].Low;
+ for(var i=0;i 2000 || dMinPrice < 0 || dMaxPrice>2000 || dMinPrice < 0)
+ this.ThrowUnexpectedNode(node,'COST() 历史K线最大最小值错误, 超出(0,1000)范围');
+
+ var lMaxPrice = parseInt(dMaxPrice * 100 + 1);
+ var lMinPrice = parseInt(dMinPrice * 100 - 1);
+ var lLow = 0, lHigh = 0, lClose = 0;
+ //去掉小数
+ dMaxPrice = lMaxPrice / 100.0;
+ dMinPrice = lMinPrice / 100.0;
+ var lSpeed = lMaxPrice - lMinPrice + 1;
+ if (lSpeed < 1) return result;
+
+ var aryVolPrice=[],aryPerVol=[];
+ for(var i=0;i= aryCapital.length) continue;
+ if (aryCapital[i]>1)
+ {
+ var kItem=kData[i]
+ dHSL = kItem.Vol/aryCapital[i];
+
+ for( var j=0;j=dTotalVol*rate)
+ {
+ dCost=(dMaxPrice-dMinPrice)*j/lSpeed+dMinPrice;
+ break;
+ }
+ }
+ }
+
+ result[i]=dCost;
+ }
+
+ return result;
+ }
+
+ /*
+ 获利盘比例.
+ 用法:
+ WINNER(CLOSE),表示以当前收市价卖出的获利盘比例,例如返回0.1表示10%获利盘;WINNER(10.5)表示10.5元价格的获利盘比例
+ 该函数仅对日线分析周期有效
+ !!!!计算比较耗时间
+ */
+ this.WINNER = function (data,node)
+ {
+ var result=[];
+ var kData=this.SymbolData.Data.Data;
+ if (!kData || kData.length<=0) return result;
+ var aryCapital=this.SymbolData.GetStockCacheData({ FunctionName:"FINANCE", Args:[7], ArgCount:1, Node:node } ); //流通股本
+
+ var dMaxPrice=kData[0].High,dMinPrice=kData[0].Low;
+ for(var i=0;i 1000 || dMinPrice < 0 || dMaxPrice>1000 || dMinPrice < 0)
+ this.ThrowUnexpectedNode(node,'WINNER() 历史K线最大最小值错误, 超出(0,1000)范围');
+
+ var lMaxPrice = parseInt(dMaxPrice * 100 + 1);
+ var lMinPrice = parseInt(dMinPrice * 100 - 1);
+ var lLow = 0, lHigh = 0, lClose = 0;
+ //去掉小数
+ dMaxPrice = lMaxPrice / 100.0;
+ dMinPrice = lMinPrice / 100.0;
+ var lSpeed = lMaxPrice - lMinPrice + 1;
+ if (lSpeed < 1) return result;
+
+ var aryVolPrice=[],aryPerVol=[];
+ for(var i=0;i= aryCapital.length) continue;
+ if (!(aryCapital[i]>1)) continue;
+ var kItem=kData[i]
+ dHSL = kItem.Vol/aryCapital[i];
+
+ for( var j=0;j 0) result[i]=dVol / dTotalVol;
+ else if (i - 1 >= 0) result[i] = result[i - 1];
+ }
+
+ return result;
+ }
+
+ //计算截至到某一天的历史所有筹码
+ this.CalculateChip = function (index, exchangeData, hisData, dRate)
+ {
+ var result = { Min: null, Max: null, Data: [] };
+ var seed = 1;//筹码历史衰减换手系数
+ var max = null, min = null;
+ for (let i = index; i >= 0; --i)
+ {
+ let item = {}; //Vol:量 High:最高 Low:最低
+ var kData = hisData[i];
+ if (i == index) item.Vol = kData.Vol * exchangeData[i];
+ else item.Vol = kData.Vol * seed;
+
+ item.Date = kData.Date;
+ item.High = kData.High;
+ item.Low = kData.Low;
+
+ if (max == null) max = item.High;
+ else if (max < item.High) max = item.High;
+ if (min == null) min = item.Low;
+ else if (min < item.Low) min = item.Low;
+
+ result.Data[i] = item;
+
+ seed *= (1 - (exchangeData[i] / 100) * dRate); //换手率累乘
+ }
+
+ result.Max = max;
+ result.Min = min;
+
+ return result;
+ }
+
+ /*
+ 返回是否连涨周期数.
+ 用法:
+ UPNDAY(CLOSE,M)
+ 表示连涨M个周期,M为常量
+ */
+ this.UPNDAY = function (data, n)
+ {
+ var result = [];
+ if (n < 1) return result;
+ if (data == null || n > data.length) return result;
+
+ var days = 0;
+ for (let i = 0; i < data.length; ++i)
+ {
+ result[i] = 0;
+ if (i - 1 < 0) continue;
+ if (!this.IsNumber(data[i]) || !this.IsNumber(data[i - 1])) //无效数都不算连涨
+ {
+ days = 0;
+ continue;
+ }
+
+ if (data[i] > data[i - 1])++days;
+ else days = 0;
+
+ if (days == n)
+ {
+ result[i] = 1;
+ --days;
+ }
+ }
+
+ return result;
+ }
+
+ /*
+ 返回是否连跌周期.
+ 用法:
+ DOWNNDAY(CLOSE,M)
+ 表示连跌M个周期,M为常量
+ */
+ this.DOWNNDAY = function (data, n)
+ {
+ var result = [];
+ if (n < 1) return result;
+ if (data == null || n > data.length) return result;
+
+ var days = 0;
+ for (let i = 0; i < data.length; ++i)
+ {
+ result[i] = 0;
+ if (i - 1 < 0) continue;
+ if (!this.IsNumber(data[i]) || !this.IsNumber(data[i - 1])) //无效数都不算连涨
+ {
+ days = 0;
+ continue;
+ }
+
+ if (data[i] < data[i - 1])++days;
+ else days = 0;
+
+ if (days == n)
+ {
+ result[i] = 1;
+ --days;
+ }
+ }
+
+ return result;
+ }
+
+ /*
+ 返回是否持续存在X>Y
+ 用法:
+ NDAY(CLOSE,OPEN,3)
+ 表示连续3日收阳线
+ */
+ this.NDAY = function (data, data2, n)
+ {
+ var result = [];
+ if (n < 1) return result;
+ if (!Array.isArray(data) && !Array.isArray(data2)) return result;
+ if (data == null || data2 == null) return result;
+
+ if (Array.isArray(data) && Array.isArray(data2))
+ {
+ if (n >= data.length || n >= data2.length) return result;
+ var count = Math.max(data.length, data2.length);
+ var days = 0;
+ for (let i = 0; i < count; ++i)
+ {
+ result[i] = 0;
+ if (i >= data.length || i >= data2.length) continue;
+ if (!this.IsNumber(data[i]) || !this.IsNumber(data2[i]))
+ {
+ days = 0;
+ continue;
+ }
+
+ if (data[i] > data2[i])++days;
+ else days = 0;
+
+ if (days == n)
+ {
+ result[i] = 1;
+ --days;
+ }
+ }
+ }
+ else if (Array.isArray(data) && !Array.isArray(data2))
+ {
+ if (n >= data.length || !this.IsNumber(data2)) return;
+ var days = 0;
+ for (let i in data)
+ {
+ result[i] = 0;
+ if (!this.IsNumber(data[i]))
+ {
+ days = 0;
+ continue;
+ }
+
+ if (data[i] > data2)++days;
+ else days = 0;
+
+ if (days == n)
+ {
+ result[i] = 1;
+ --days;
+ }
+ }
+ }
+ else if (!Array.isArray(data) && Array.isArray(data2))
+ {
+ if (n >= data2.length || !this.IsNumber(data)) return;
+ var days = 0;
+ for (let i in data2)
+ {
+ result[i] = 0;
+ if (!this.IsNumber(data2[i]))
+ {
+ days = 0;
+ continue;
+ }
+
+ if (data > data2[i])++days;
+ else days = 0;
+
+ if (days == n)
+ {
+ result[i] = 1;
+ --days;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ /*
+ 两条线维持一定周期后交叉.
+ 用法:LONGCROSS(A,B,N)表示A在N周期内都小于B,本周期从下方向上穿过B时返回1,否则返回0
+ */
+ this.LONGCROSS = function (data, data2, n)
+ {
+ var result = [];
+ var count = Math.max(data.length, data2.length);
+ for (let i = 0; i < count; ++i)
+ {
+ result[i] = 0;
+ if (i - 1 < 0) continue;
+ if (i >= data.length || i >= data2.length) continue;
+ if (!this.IsNumber(data[i]) || !this.IsNumber(data2[i]) || !this.IsNumber(data[i - 1]) || !this.IsNumber(data2[i - 1])) continue;
+
+ if (data[i] > data2[i] && data[i - 1] < data2[i - 1]) result[i] = 1;
+ }
+
+ for (let i = 0, j = 0; i < count; ++i)
+ {
+ if (!result[i]) continue;
+
+ for (j = 1; j <= n && i - j >= 0; ++j)
+ {
+ if (data[i - j] >= data2[i - j])
+ {
+ result[i] = 0;
+ break;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ /*
+ EXISTR(X,A,B):是否存在(前几日到前几日间).
+ 例如: EXISTR(CLOSE>OPEN,10,5)
+ 表示从前10日内到前5日内存在着阳线
+ 若A为0,表示从第一天开始,B为0,表示到最后日止
+ */
+ this.EXISTR = function (data, n, n2)
+ {
+ var result = [];
+ if (!Array.isArray(data)) return result;
+
+ n = parseInt(n);
+ n2 = parseInt(n2);
+ if (n <= 0) n = data.length;
+ if (n2 <= 0) n2 = 1;
+ if (n2 > n) return result;
+
+ var result = [];
+ var value;
+ for (let i = 0, j = 0; i < data.length; ++i)
+ {
+ result[i] = null;
+ if (i - n < 0 || i - n2 < 0) continue;
+
+ result[i] = 0;
+ for (j = n; j >= n2; --j)
+ {
+ var value = data[i - j];
+ if (this.IsNumber(value) && value)
+ {
+ result[i] = 1;
+ break;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ /*
+ RELATE(X,Y,N) 返回X和Y的N周期的相关系数
+ RELATE(X,Y,N)=(∑[(Xi-Avg(X))(Yi-Avg(y))])/N ÷ √((∑(Xi-Avg(X))^2)/N * (∑(Yi-Avg(Y))^2)/N)
+ 其中 avg(x)表示x的N周期均值: avg(X) = (∑Xi)/N
+ √(...)表示开平方
+ */
+ this.RELATE = function (data, data2, n)
+ {
+ var result = [];
+ if (n < 1) n = 1;
+
+ if (!Array.isArray(data) || !Array.isArray(data2)) return result;
+
+ var dataAverage = this.CalculateAverage(data, n);
+ var data2Average = this.CalculateAverage(data2, n);
+
+ var count = Math.max(data.length, data2.length);
+ for (let i = 0, j = 0; i < count; ++i)
+ {
+ result[i] = null;
+
+ if (i >= data.length || i >= data2.length || i >= dataAverage.length || i >= data2Average.length) continue;
+
+ var average = dataAverage[i];
+ var average2 = data2Average[i];
+
+ var total = 0, total2 = 0, total3 = 0;
+ for (j = i - n + 1; j <= i; ++j)
+ {
+ total += (data[j] - average) * (data2[j] - average2); //∑[(Xi-Avg(X))(Yi-Avg(y))])
+ total2 += Math.pow(data[j] - average, 2); //∑(Xi-Avg(X))^2
+ total3 += Math.pow(data2[j] - average2, 2); //∑(Yi-Avg(Y))^2)
+ }
+
+ result[i] = (total / n) / (Math.sqrt(total2 / n) * Math.sqrt(total3 / n));
+ }
+
+ return result;
+ }
+
+ //计算数组n周期内的均值
+ this.CalculateAverage = function (data, n)
+ {
+ var result = [];
+ if (n < 1) return result;
+
+ var total = 0;
+
+ for (var i = 0; i < data.length; ++i) //去掉开始的无效数
+ {
+ if (this.IsNumber(data[i])) break;
+ }
+
+ for (; i < data.length && i < n; ++i) //计算第1个周期的数据
+ {
+ result[i] = null;
+ var value = data[i];
+ if (!this.IsNumber(value)) continue;
+ total += value;
+ }
+ result[i - 1] = total / n;
+
+ for (; i < data.length; ++i) //计算后面的周期数据
+ {
+ var value = data[i];
+ var preValue = data[i - n]; //上一个周期的第1个数据
+ if (!this.IsNumber(value)) value = 0;
+ if (!this.IsNumber(preValue)) preValue = 0;
+
+ total = total - preValue + value; //当前周期的数据 等于上一个周期数据 去掉上一个周期的第1个数据 加上这个周期的最后1个数据
+ result[i] = total / n;
+ }
+
+ return result;
+ }
+
+ /*
+ COVAR(X,Y,N) 返回X和Y的N周期的协方差
+ */
+ this.COVAR = function (data, data2, n)
+ {
+ var result = [];
+ if (n < 1) n = 1;
+
+ if (!Array.isArray(data) || !Array.isArray(data2)) return result;
+
+ var dataAverage = this.CalculateAverage(data, n);
+ var data2Average = this.CalculateAverage(data2, n);
+
+ var count = Math.max(data.length, data2.length);
+
+ var count = Math.max(data.length, data2.length);
+ for (let i = 0, j = 0; i < count; ++i)
+ {
+ result[i] = null;
+
+ if (i >= data.length || i >= data2.length || i >= dataAverage.length || i >= data2Average.length) continue;
+
+ var average = dataAverage[i];
+ var average2 = data2Average[i];
+
+ var total = 0;
+ for (j = i - n + 1; j <= i; ++j)
+ {
+ total += (data[j] - average) * (data2[j] - average2);
+ }
+
+ result[i] = (total / n);
+ }
+
+ return result;
+ }
+
+ /*
+ 求上一高点到当前的周期数.
+ 用法:
+ HHVBARS(X,N):求N周期内X最高值到当前周期数,N=0表示从第一个有效值开始统计
+ 例如:
+ HHVBARS(HIGH,0)求得历史新高到到当前的周期数
+ */
+ this.HHVBARS = function (data, n)
+ {
+ var result = [];
+ if (!Array.isArray(data)) return result;
+ if (Array.isArray(n))
+ {
+ for(var i=0;i=data[nMax]) nMax=j;
+ }
+
+ if (nMax!=null)
+ result[i]=(i-nMax);
+ }
+ }
+ else
+ {
+ if (n < 1) n = data.length;
+
+ var nMax = null; //最大值索引
+ for (var i = 0; i < data.length; ++i)
+ {
+ result[i] = null;
+ if (this.IsNumber(data[i])) {
+ nMax = i;
+ break;
+ }
+ }
+
+ var j = 0;
+ for (i = nMax + 1; i < data.length && j < n; ++i, ++j) //求第1个最大值
+ {
+ if (data[i] >= data[nMax]) nMax = i;
+ if (n == data.length) result[i] = (i - nMax);
+ }
+
+ for (; i < data.length; ++i)
+ {
+ if (i - nMax < n)
+ {
+ if (data[i] >= data[nMax]) nMax = i;
+ }
+ else
+ {
+ nMax = i - n + 1;
+ for (j = nMax; j <= i; ++j) //计算区间最大值
+ {
+ if (data[j] >= data[nMax]) nMax = j;
+ }
+ }
+
+ result[i] = i - nMax;
+ }
+ }
+
+ return result;
+ }
+
+ /*
+ 求上一低点到当前的周期数.
+ 用法: LLVBARS(X,N):求N周期内X最低值到当前周期数,N=0表示从第一个有效值开始统计
+ 例如: LLVBARS(HIGH,20)求得20日最低点到当前的周期数
+ */
+ this.LLVBARS = function (data, n)
+ {
+ var result = [];
+ if (!Array.isArray(data)) return result;
+ if (Array.isArray(n))
+ {
+ for(var i=0;i 0 && stockItem.YClose > 0) stockProfit[i] = (stockItem.Close - stockItem.YClose) / stockItem.YClose;
+ if (indexItem.Close > 0 && indexItem.YClose > 0) indexProfit[i] = (indexItem.Close - indexItem.YClose) / indexItem.YClose;
+ }
+
+ //计算均值数组
+ var averageStockProfit = this.CalculateAverage(stockProfit, n);
+ var averageIndexProfit = this.CalculateAverage(indexProfit, n);
+
+ for (var i = 0, j = 0; i < stockData.Data.length; ++i)
+ {
+ result[i] = null;
+ if (i >= stockProfit.length || i >= indexProfit.length || i >= averageStockProfit.length || i >= averageIndexProfit.length) continue;
+
+ var averageStock = averageStockProfit[i];
+ var averageIndex = averageIndexProfit[i];
+
+ var covariance = 0; //协方差
+ var variance = 0; //方差
+ for (j = i - n + 1; j <= i; ++j)
+ {
+ var value = (indexProfit[j] - averageIndex);
+ var value2 = (stockProfit[j] - averageStock);
+ covariance += value * value2;
+ variance += value * value;
+ }
+
+ if (this.IsDivideNumber(variance) && this.IsNumber(covariance))
+ result[i] = covariance / variance; //(covariance/n)/(variance/n)=covariance/variance;
+ }
+
+ return result;
+ }
+
+ /*
+ 用法:BETA2(X,Y,N)为X与Y的N周期相关放大系数,表示Y变化1%,则X将变化N%
+ 例如:BETA2(CLOSE,INDEXC,10)表示收盘价与大盘指数之间的10周期相关放大率
+ */
+ this.BETA2 = function (x, y, n)
+ {
+ var result = [];
+ if (n <= 0) n = 1;
+
+ var xProfit = [null]; //x数据的涨幅
+ var yProfit = [null]; //y数据的涨幅
+
+ var count = Math.max(x.length, y.length);
+
+ var lastItem = { X: x[0], Y: y[0] };
+ for (var i = 1; i < count; ++i)
+ {
+ xProfit[i] = 0;
+ yProfit[i] = 0;
+
+ var xItem = x[i];
+ var yItem = y[i];
+
+ if (lastItem.X > 0) xProfit[i] = (xItem - lastItem.X) / lastItem.X;
+ if (lastItem.Y > 0) yProfit[i] = (yItem - lastItem.Y) / lastItem.Y;
+
+ lastItem = { X: xItem, Y: yItem };
+ }
+
+ //计算均值数组
+ var averageXProfit = this.CalculateAverage(xProfit, n);
+ var averageYProfit = this.CalculateAverage(yProfit, n);
+
+ for (var i = 0, j = 0; i < count; ++i)
+ {
+ result[i] = null;
+
+ if (i >= xProfit.length || i >= yProfit.length || i >= averageXProfit.length || i >= averageYProfit.length) continue;
+
+ var averageX = averageXProfit[i];
+ var averageY = averageYProfit[i];
+
+ var covariance = 0; //协方差
+ var variance = 0; //方差
+ for (j = i - n + 1; j <= i; ++j)
+ {
+ var value = (xProfit[j] - averageX);
+ var value2 = (yProfit[j] - averageY);
+ covariance += value * value2;
+ variance += value * value;
+ }
+
+ if (this.IsDivideNumber(variance) && this.IsNumber(covariance))
+ result[i] = covariance / variance; //(covariance/n)/(variance/n)=covariance/variance;
+ }
+
+ return result;
+ }
+
+ /*
+ 抛物转向.
+ 用法:
+ SAR(N,S,M),N为计算周期,S为步长,M为极值
+ 例如:
+ SAR(10,2,20)表示计算10日抛物转向,步长为2%,极限值为20%
+ */
+ this.SAR = function (n, step, exValue)
+ {
+ var result = [];
+ var stockData = this.SymbolData.Data;
+ if (n >= stockData.Data.length) return result;
+
+ var high = null, low = null;
+ for (var i = 0; i < n; ++i)
+ {
+ var item = stockData.Data[i];
+ if (high == null) high = item.High;
+ else if (high < item.High) high = item = high;
+ if (low == null) low = item.Low;
+ else if (low > item.Low) low = item.Low;
+ }
+
+ const SAR_LONG = 0, SAR_SHORT = 1;
+ var position = SAR_LONG;
+ result[n - 1] = low;
+ var nextSar = low, sip = stockData.Data[0].High, af = exValue / 100;
+ for (var i = n; i < stockData.Data.length; ++i)
+ {
+ var ysip = sip;
+ var item = stockData.Data[i];
+ var yitem = stockData.Data[i - 1];
+
+ if (position == SAR_LONG)
+ {
+ if (item.Low < result[i - 1])
+ {
+ position = SAR_SHORT;
+ sip = item.Low;
+ af = step / 100;
+ nextSar = Math.max(item.High, yitem.High);
+ nextSar = Math.max(nextSar, ysip + af * (sip - ysip));
+ }
+ else
+ {
+ position = SAR_LONG;
+ if (item.High > ysip)
+ {
+ sip = item.High;
+ af = Math.min(af + step / 100, exValue / 100);
+ }
+ nextSar = Math.min(item.Low, yitem.Low);
+ nextSar = Math.min(nextSar, result[i - 1] + af * (sip - result[i - 1]));
+ }
+ }
+ else if (position == SAR_SHORT)
+ {
+ if (item.High > result[i - 1])
+ {
+ position = SAR_LONG;
+ sip = item.High;
+ af = step / 100;
+ nextSar = Math.min(item.Low, yitem.Low);
+ nextSar = Math.min(nextSar, result[i - 1] + af * (sip - ysip));
+ }
+ else
+ {
+ position = SAR_SHORT;
+ if (item.Low < ysip)
+ {
+ sip = item.Low;
+ af = Math.min(af + step / 100, exValue / 100);
+ }
+ nextSar = Math.max(item.High, yitem.High);
+ nextSar = Math.max(nextSar, result[i - 1] + af * (sip - result[i - 1]));
+ }
+ }
+
+ result[i] = nextSar;
+ }
+
+ return result;
+ }
+
+ /*
+ 抛物转向点.
+ 用法:
+ SARTURN(N,S,M),N为计算周期,S为步长,M为极值,若发生向上转向则返回1,若发生向下转向则返回-1,否则为0
+ 其用法与SAR函数相同
+ */
+ this.SARTURN = function (n, step, exValue)
+ {
+ var result = [];
+ var sar = this.SAR(n, step, exValue);
+ var stockData = this.SymbolData.Data;
+ var index = 0;
+ for (index = 0; index < sar.length; ++index)
+ {
+ if (this.IsNumber(sar[index])) break;
+ }
+ var flag = 0;
+ if (index < stockData.Data.length) flag = stockData.Data[index].Close > sar[index];
+
+ for (var i = index + 1; i < stockData.Data.length; ++i)
+ {
+ var item = stockData.Data[i];
+ if (item.Close < sar[i] && flag) result[i] = -1;
+ else result[i] = (item.Close > sar[i] && !flag) ? 1 : 0;
+
+ flag = item.Close > sar[i];
+ }
+
+ return result;
+ }
+
+ /*
+ 属于未来函数,将当前位置到若干周期前的数据设为1.
+ 用法:
+ BACKSET(X,N),若X非0,则将当前位置到N周期前的数值设为1.
+ 例如:
+ BACKSET(CLOSE>OPEN,2)若收阳则将该周期及前一周期数值设为1,否则为0
+ */
+ this.BACKSET = function (condition, n)
+ {
+ var result = [];
+ if (!condition) return result;
+ var dataCount = condition.length;
+ if (!this.IsNumber(dataCount) || dataCount <= 0) return result;
+ if (Array.isArray(n))
+ {
+ for(var i=0;i=0 && k= 0; --i)
+ {
+ var value = condition[i];
+ if (this.IsNumber(value) && value)
+ {
+ for (j = i; j > i - num; --j)
+ {
+ result[j] = 1;
+ }
+ }
+ }
+
+ if (condition[i])
+ {
+ for (j = i; j >= pos; --j) result[j] = 1;
+ }
+ }
+
+ return result;
+ }
+
+ //STRCAT(A,B):将两个字符串A,B(非序列化)相加成一个字符串C.
+ //用法: STRCAT('多头','开仓')将两个字符串'多头','开仓'相加成一个字符串'多头开仓'
+ this.STRCAT = function (str1, str2)
+ {
+ var result=[];
+ if (this.IsString(str1) && this.IsString(str2))
+ result=str1+str2;
+ return result;
+ }
+
+ //VARCAT(A,B):将两个字符串A,B相加成一个字符串C.
+ //用法: DRAWTEXT(CLOSE>OPEN,LOW,VARCAT('多头',VAR2STR(C,2))) 将两个字符串相加成一个字符串并按条件显示出来
+ this.VARCAT=function(data,data2)
+ {
+ var result=[];
+ if (Array.isArray(data) && Array.isArray(data2))
+ {
+ var nCount=Math.max(data.length, data2.length);
+ var strValue="";
+ for(var i=0;i= 0; --i)
+ {
+ var item = data[i];
+ if (this.IsNumber(item))
+ {
+ result = item.toFixed(n);
+ return result;
+ }
+ }
+ }
+ else
+ {
+ if (this.IsNumber(data))
+ result = data.toFixed(n);
+ }
+
+ return result;
+ }
+
+ //VAR2STR(A,N):取A的每一个值转为字符串,小数位数N.
+ //用法: VAR2STR(C,3)表示取收盘价,以3位小数转为字符串
+ this.VAR2STR=function(data,n)
+ {
+ var result=[];
+ if (Array.isArray(data))
+ {
+ for(var i=0;iOPEN)表示统计连续收阳的周期数
+ */
+ this.BARSLASTCOUNT=function(data)
+ {
+ var result=null;
+ if (Array.isArray(data))
+ {
+ result=[];
+ if (data.length>0)
+ {
+ var count=0;
+ for(var i=data.length-1;i>=0;--i)
+ {
+ count=0;
+ for(var j=i;j>=0;--j)
+ {
+ if (data[j]) ++count;
+ else break;
+ }
+ result[i]=count;
+ }
+ }
+ }
+ else
+ {
+ if (data) result=1;
+ else result=0;
+ }
+ return result;
+ }
+
+ //取整.
+ //用法: INTPART(A)返回沿A绝对值减小方向最接近的整数
+ //例如:INTPART(12.3)求得12,INTPART(-3.5)求得-3
+ this.INTPART=function(data)
+ {
+ var result=null;
+ if (Array.isArray(data))
+ {
+ result=[];
+ for(var i in data)
+ {
+ var item=data[i];
+ if (this.IsNumber(item)) result[i]=parseInt(item);
+ else result[i]=null;
+ }
+ }
+ else if (this.IsNumber(data))
+ {
+ result=parseInt(data);
+ }
+
+ return result;
+ }
+
+ //函数调用
+ this.CallFunction=function(name,args,node)
+ {
+ switch(name)
+ {
+ case 'MAX':
+ return this.MAX(args[0], args[1]);
+ case 'MIN':
+ return this.MIN(args[0], args[1]);
+ case 'REF':
+ return this.REF(args[0], args[1]);
+ case "REFV":
+ return this.REFV(args[0], args[1]);
+ case 'REFX':
+ return this.REFX(args[0], args[1]);
+ case "REFXV":
+ return this.REFXV(args[0], args[1]);
+ case 'ABS':
+ return this.ABS(args[0]);
+ case 'MA':
+ return this.MA(args[0], args[1]);
+ case "EMA":
+ return this.EMA(args[0], args[1]);
+ case "SMA":
+ return this.SMA(args[0], args[1],args[2]);
+ case "DMA":
+ return this.DMA(args[0], args[1]);
+ case "XMA":
+ return this.XMA(args[0], args[1]);
+ case 'EXPMA':
+ return this.EXPMA(args[0], args[1]);
+ case 'EXPMEMA':
+ return this.EXPMEMA(args[0], args[1]);
+ case 'COUNT':
+ return this.COUNT(args[0], args[1]);
+ case 'LLV':
+ return this.LLV(args[0], args[1]);
+ case 'LLVBARS':
+ return this.LLVBARS(args[0], args[1]);
+ case 'HHV':
+ return this.HHV(args[0], args[1]);
+ case 'HHVBARS':
+ return this.HHVBARS(args[0], args[1]);
+ case 'MULAR':
+ return this.MULAR(args[0], args[1]);
+ case 'CROSS':
+ return this.CROSS(args[0], args[1]);
+ case 'LONGCROSS':
+ return this.LONGCROSS(args[0], args[1], args[2]);
+ case 'AVEDEV':
+ return this.AVEDEV(args[0], args[1]);
+ case 'STD':
+ return this.STD(args[0], args[1]);
+ case 'IF':
+ case 'IFF':
+ return this.IF(args[0], args[1], args[2]);
+ case 'IFN':
+ return this.IFN(args[0], args[1], args[2]);
+ case 'NOT':
+ return this.NOT(args[0]);
+ case 'SUM':
+ return this.SUM(args[0], args[1]);
+ case 'RANGE':
+ return this.RANGE(args[0],args[1],args[2]);
+ case 'EXIST':
+ return this.EXIST(args[0],args[1]);
+ case 'EXISTR':
+ return this.EXISTR(args[0], args[1], args[2]);
+ case 'FILTER':
+ return this.FILTER(args[0], args[1]);
+ case 'TFILTER':
+ return this.TFILTER(args[0],args[1],args[2]);
+ case 'SLOPE':
+ return this.SLOPE(args[0],args[1]);
+ case 'BARSLAST':
+ return this.BARSLAST(args[0]);
+ case 'BARSCOUNT':
+ return this.BARSCOUNT(args[0]);
+ case 'BARSSINCEN':
+ return this.BARSSINCEN(args[0], args[1]);
+ case 'BARSSINCE':
+ return this.BARSSINCE(args[0]);
+ case 'LAST':
+ return this.LAST(args[0], args[1], args[2]);
+ case 'EVERY':
+ return this.EVERY(args[0], args[1]);
+ case 'ZIG':
+ return this.ZIG(args[0], args[1]);
+ case 'TROUGHBARS':
+ return this.TROUGHBARS(args[0], args[1], args[2]);
+ case "TROUGH":
+ return this.TROUGH(args[0],args[1],args[2]);
+ case 'PEAKBARS':
+ return this.PEAKBARS(args[0], args[1], args[2]);
+ case 'PEAK':
+ return this.PEAK(args[0],args[1],args[2]);
+ case 'COST':
+ return this.COST(args[0], node);
+ case 'WINNER':
+ return this.WINNER(args[0], node);
+ case 'UPNDAY':
+ return this.UPNDAY(args[0], args[1]);
+ case 'DOWNNDAY':
+ return this.DOWNNDAY(args[0], args[1]);
+ case 'NDAY':
+ return this.NDAY(args[0], args[1], args[2]);
+ case 'DEVSQ':
+ return this.DEVSQ(args[0], args[1]);
+ case 'FORCAST':
+ return this.FORCAST(args[0], args[1]);
+ case 'STDP':
+ return this.STDP(args[0], args[1]);
+ case 'VAR':
+ return this.VAR(args[0], args[1]);
+ case 'VARP':
+ return this.VARP(args[0], args[1]);
+ case 'RELATE':
+ return this.RELATE(args[0], args[1], args[2]);
+ case 'COVAR':
+ return this.COVAR(args[0], args[1], args[2]);
+ case 'BETA':
+ return this.BETA(args[0]);
+ case 'BETA2':
+ return this.BETA2(args[0], args[1], args[2]);
+ case 'WMA':
+ return this.WMA(args[0], args[1]);
+ case 'MEMA':
+ return this.MEMA(args[0], args[1]);
+ case 'SUMBARS':
+ return this.SUMBARS(args[0], args[1]);
+ case 'REVERSE':
+ return this.REVERSE(args[0]);
+ case 'SAR':
+ return this.SAR(args[0], args[1], args[2]);
+ case 'SARTURN':
+ return this.SARTURN(args[0], args[1], args[2]);
+ case 'BACKSET':
+ return this.BACKSET(args[0], args[1]);
+ case 'STRCAT':
+ return this.STRCAT(args[0], args[1]);
+ case "VARCAT":
+ return this.VARCAT(args[0], args[1]);
+ case "VAR2STR":
+ return this.VAR2STR(args[0], args[1]);
+ case 'CON2STR':
+ return this.CON2STR(args[0], args[1]);
+ case "STRSPACE":
+ return this.STRSPACE(args[0]);
+ case 'DTPRICE':
+ return this.DTPRICE(args[0], args[1]);
+ case 'ZTPRICE':
+ return this.ZTPRICE(args[0], args[1]);
+ case 'FRACPART':
+ return this.FRACPART(args[0]);
+ case 'BARSLASTCOUNT':
+ return this.BARSLASTCOUNT(args[0]);
+ case 'INTPART':
+ return this.INTPART(args[0]);
+ //三角函数
+ case 'ATAN':
+ return this.Trigonometric(args[0], Math.atan);
+ case 'ACOS':
+ return this.ACOS(args[0]);
+ case 'ASIN':
+ return this.ASIN(args[0]);
+ case 'COS':
+ return this.Trigonometric(args[0], Math.cos);
+ case 'SIN':
+ return this.Trigonometric(args[0], Math.sin);
+ case 'TAN':
+ return this.Trigonometric(args[0], Math.tan);
+ case 'LN':
+ return this.Trigonometric(args[0], Math.log);
+ case 'LOG':
+ return this.Trigonometric(args[0], Math.log10);
+ case 'EXP':
+ return this.Trigonometric(args[0], Math.exp);
+ case 'SQRT':
+ return this.Trigonometric(args[0], Math.sqrt);
+ default:
+ this.ThrowUnexpectedNode(node,'函数'+name+'不存在');
+ }
+ }
+
+ //调用自定义函数 返回数据格式{Out:输出数据, Draw:绘图数据(可选)}
+ this.CallCustomFunction=function(name, args, symbolData, node)
+ {
+ var functionInfo=g_JSComplierResource.CustomFunction.Data.get(name);
+ var dwonloadData=symbolData.GetStockCacheData({ CustomName:name, Node:node });
+ if (!functionInfo.Invoke)
+ return { Out: dwonloadData }
+
+ JSConsole.Complier.Log('[JSAlgorithm::CallCustomFunction] call custom function functionInfo=',functionInfo);
+
+ var self=this;
+ var obj=
+ {
+ Name:name,
+ Args:args,
+ Symbol:symbolData.Symbol, Period:symbolData.Period, Right:symbolData.Right,
+ KData:symbolData.Data, //K线数据
+ DownloadData:dwonloadData,
+ ThrowError:function(error)
+ {
+ self.ThrowUnexpectedNode(node, error);
+ }
+ };
+
+ return functionInfo.Invoke(obj);
+ }
+
+ this.ThrowUnexpectedNode=function(node,message)
+ {
+ let marker=node.Marker;
+ let msg=message || "执行异常";
+
+ return this.ErrorHandler.ThrowError(marker.Index,marker.Line,marker.Column,msg);
+
+ }
+}
+
+//是否有是有效的数字
+JSAlgorithm.prototype.IsNumber=function(value)
+{
+ if (value==null) return false;
+ if (isNaN(value)) return false;
+
+ return true;
+}
+
+//是否是整形
+JSAlgorithm.prototype.IsInteger=function(x)
+{
+ return (typeof x === 'number') && (x % 1 === 0);
+}
+
+
+//是否有是有效的除数
+JSAlgorithm.prototype.IsDivideNumber=function(value)
+{
+ if (value==null) return false;
+ if (isNaN(value)) return false;
+ if (value==0) return false;
+
+ return true;
+}
+
+//是否是字符串
+JSAlgorithm.prototype.IsString=function(value)
+{
+ if (value && typeof(value)=='string') return true;
+ return false;
+}
+
+/*
+ 绘图函数
+*/
+function JSDraw(errorHandler, symbolData)
+{
+ this.ErrorHandler=errorHandler;
+ this.SymbolData = symbolData;
+
+ this.DRAWTEXT=function(condition,price,text)
+ {
+ let drawData=[];
+ let result={DrawData:drawData, DrawType:'DRAWTEXT',Text:text};
+
+ if (Array.isArray(condition))
+ {
+ var IsNumber=this.IsNumber(price);
+ for(var i in condition)
+ {
+ drawData[i]=null;
+
+ if (isNaN(condition[i]) || !condition[i]) continue;
+
+ if (IsNumber)
+ {
+ drawData[i]=price;
+ }
+ else
+ {
+ if (this.IsNumber(price[i])) drawData[i]=price[i];
+ }
+ }
+ }
+ else if (this.IsNumber(condition) && condition)
+ {
+ var IsNumber=this.IsNumber(price);
+ for(var i=0;i=HHV(HIGH,20),HIGH,LOW<=LLV(LOW,20),LOW,1) 表示在创20天新高与创20天新低之间画直线并且向右延长。
+ */
+ this.DRAWLINE=function(condition,data,condition2,data2,expand)
+ {
+ let drawData=[];
+ let result={DrawData:drawData, DrawType:'DRAWLINE', Expand:expand};
+
+ if(condition.length<=0) return result;
+ let count=Math.max(condition.length,condition2.length);
+
+ let bFirstPoint=false;
+ let bSecondPont=false;
+ let lineCache={Start:{ },End:{ }, List:new Array()};
+
+ for(let i=0;i=0;--i)
+ {
+ if (this.IsNumber(drawData[i]))
+ {
+ x2=i;
+ break;
+ }
+ }
+ //y3=(y1-y2)*(x3-x1)/(x2-x1)
+ if (x2!=null && x2-1>=0)
+ {
+ var x1=x2-1;
+ for(var i=x2+1;iVAL2时,在VAL1和VAL2之间填充COLOR1;当VAL1=HHV(HIGH,20),HIGH)表示在创20天新高点之间画折线。
+ */
+ this.POLYLINE = function (condition, data)
+ {
+ let drawData = [];
+ let result = { DrawData: drawData, DrawType: 'POLYLINE' };
+ let isNumber = typeof (data) == 'number';
+
+ let bFirstPoint = false;
+ let bSecondPont = false;
+ if (isNumber)
+ {
+ for (let i in condition)
+ {
+ drawData[i] = null;
+ if (bFirstPoint == false)
+ {
+ if (!condition[i]) continue;
+
+ drawData[i] = data;
+ bFirstPoint = true;
+ }
+ else {
+ drawData[i] = data;
+ }
+ }
+ }
+ else
+ {
+ let lineCache = { Start: {}, End: {}, List: new Array() };
+ for (let i in condition)
+ {
+ drawData[i] = null;
+ if (bFirstPoint == false && bSecondPont == false)
+ {
+ if (condition[i] == null || !condition[i]) continue;
+ if (i >= data.length || !this.IsNumber(data[i])) continue;
+
+ bFirstPoint = true;
+ lineCache.Start = { ID: parseInt(i), Value: data[i] }; //第1个点
+ }
+ else if (bFirstPoint == true && bSecondPont == false)
+ {
+ if (condition[i] == null || !condition[i]) continue;
+ if (i >= data.length || !this.IsNumber(data[i])) continue;
+
+ lineCache.End = { ID: parseInt(i), Value: data[i] }; //第2个点
+ //根据起始点和结束点 计算中间各个点的数据
+ let lineData = this.CalculateDrawLine(lineCache); //计算2个点的线上 其他点的数值
+
+ for (let j in lineData)
+ {
+ let item = lineData[j];
+ drawData[item.ID] = item.Value;
+ }
+
+ let start = { ID: lineCache.End.ID, Value: lineCache.End.Value };
+ lineCache = { Start: start, End: {} };
+ }
+ }
+ }
+
+ return result
+ }
+
+ /*
+ 画出数字.
+ 用法:
+ DRAWNUMBER(COND,PRICE,NUMBER),当COND条件满足时,在PRICE位置书写数字NUMBER.
+ 例如:
+ DRAWNUMBER(CLOSE/OPEN>1.08,LOW,C)表示当日实体阳线大于8%时在最低价位置显示收盘价.
+ */
+ this.DRAWNUMBER = function (condition, data, data2)
+ {
+ let drawData = { Value: new Array(), Text: new Array() };
+ let result = { DrawData: drawData, DrawType: 'DRAWNUMBER' };
+ var isArrayData=Array.isArray(data);
+ let isNumber = typeof (data2) == 'number';
+ let text;
+ if (isNumber)
+ {
+ if (this.IsInteger(data2)) text=data2.toString();
+ else text=data2.toFixed(2);
+ }
+
+ for (let i in condition)
+ {
+ drawData.Value[i] = null;
+ if (!condition[i]) continue;
+ if (isArrayData)
+ {
+ if (i >= data.length || !this.IsNumber(data[i])) continue;
+
+ if (isNumber)
+ {
+ drawData.Value[i] = data[i];
+ drawData.Text[i] = text;
+ }
+ else
+ {
+ if (i >= data2.length || !data2[i]) continue;
+ drawData.Value[i] = data[i];
+ if (typeof(data2[i])=='number')
+ drawData.Text[i] = data2[i].toFixed(2);
+ else
+ drawData.Text[i] = data2[i].toString();
+ }
+ }
+ else if (this.IsNumber(data))
+ {
+ if (isNumber)
+ {
+ drawData.Value[i]=data;
+ drawData.Text[i]=text;
+ }
+ else
+ {
+ if (i>=data2.length || !data2[i]) continue;
+ drawData.Value[i]=data;
+ if (this.IsNumber(data2[i]))
+ drawData.Text[i] = data2[i].toFixed(2);
+ else
+ drawData.Text[i] = data2[i].toString();
+ }
+ }
+
+ }
+
+ return result;
+ }
+
+ /*
+ 在图形上绘制小图标.
+ 用法:
+ DRAWICON(COND,PRICE,TYPE),当COND条件满足时,在PRICE位置画TYPE号图标(TYPE为1--41).
+ 例如:
+ DRAWICON(CLOSE>OPEN,LOW,1)表示当收阳时在最低价位置画1号图标.
+ */
+ this.DRAWICON = function (condition, data, type)
+ {
+ //图标对应的字符代码
+ let mapIcon = new Map([
+ [1, { Symbol: '↑', Color: 'rgb(238,44,44)' }], [2, { Symbol: '↓', Color: 'rgb(0,139,69)' }],
+ [3, { Symbol: '😧' }], [4, { Symbol: '😨' }], [5, { Symbol: '😁' }], [6, { Symbol: '😱' }],
+ [7, { Symbol: '◼', Color: 'rgb(238,44,44)' }], [8, { Symbol: '◆', Color: 'rgb(0,139,69)' }],
+ [9, { Symbol: '💰' }], [10, { Symbol: '📪' }], [11, { Symbol: '👆' }], [12, { Symbol: '👇' }],
+ [13, { Symbol: 'B', Color: 'rgb(178,34,34)' },], [14, { Symbol: 'S', Color: 'rgb(0,139,69)' }],
+ [36, { Symbol: 'Χ', Color: 'rgb(238,44,44)' }], [37, { Symbol: 'X', Color: 'rgb(0,139,69)' }],
+ [38, { Symbol: '▲', Color: 'rgb(238,44,44)' }], [39, { Symbol: '▼', Color: 'rgb(0,139,69)' }],
+ ]);
+
+ let icon = mapIcon.get(type);
+ if (!icon) icon = { Symbol: '●', Color: 'rgb(0,139,69)'};
+ let drawData = [];
+ let result = { DrawData: drawData, DrawType: 'DRAWICON', Icon: icon };
+ if (condition.length <= 0) return result;
+
+ var IsNumber = typeof (data) == "number";
+ if (typeof (condition) == 'number')
+ {
+ if (!condition) return result;
+
+ for (var i = 0; i < this.SymbolData.Data.Data.length; ++i)
+ {
+ if (IsNumber)
+ {
+ drawData[i] = data;
+ }
+ else
+ {
+ if (i < data.length && this.IsNumber(data[i])) drawData[i] = data[i];
+ else drawData[i] = null;
+ }
+ }
+ return result;
+ }
+
+ for (var i in condition)
+ {
+ drawData[i] = null;
+
+ if (!condition[i]) continue;
+
+ if (IsNumber)
+ {
+ drawData[i] = data;
+ }
+ else
+ {
+ if (this.IsNumber(data[i])) drawData[i] = data[i];
+ }
+ }
+
+ return result;
+ }
+
+ // 相对位置上画矩形.
+ //用法: DRAWRECTREL(LEFT,TOP,RIGHT,BOTTOM,COLOR),以图形窗口(LEFT,TOP)为左上角,(RIGHT,BOTTOM)为右下角绘制矩形,坐标单位是窗口沿水平和垂直方向的1/1000,取值范围是0—999,超出范围则可能显示在图形窗口外,矩形中间填充颜色COLOR,COLOR为0表示不填充.
+ //例如: DRAWRECTREL(0,0,500,500,RGB(255,255,0))表示在图形最左上部1/4位置用黄色绘制矩形
+ this.DRAWRECTREL = function (left, top, right, bottom, color)
+ {
+
+ let drawData =
+ {
+ Rect:
+ {
+ Left: Math.min(left,right), Top: Math.min(top,bottom),
+ Right: Math.max(left,right), Bottom: Math.max(top,bottom)
+ },
+ Color: color
+ };
+ if (color == 0) drawData.Color = null;
+ let result = { DrawData: drawData, DrawType: 'DRAWRECTREL' };
+
+ return result;
+ }
+
+ //填充背景.
+ //用法: DRAWGBK(COND,COLOR1,COLOR2,colorAngle) colorAngle=渐近色角度
+ //例如: DRAWGBK(O>C,RGB(0,255,0),RGB(255,0,0),0);
+ this.DRAWGBK=function(condition, color, color2, colorAngle)
+ {
+ let drawData={ Color:[], Angle:colorAngle };
+ if (color) drawData.Color.push(color);
+ if (color2) drawData.Color.push(color2);
+
+ let result={DrawData:null, DrawType:'DRAWGBK'};
+ if (Array.isArray(condition))
+ {
+ for(var i in condition)
+ {
+ var item=condition[i];
+ if (item)
+ {
+ result.DrawData=drawData;
+ break;
+ }
+ }
+ }
+ else
+ {
+ if (condition) result.DrawData=drawData;
+ }
+
+ return result;
+ }
+
+ this.DRAWGBK2=function(condition, color, color2, colorAngle)
+ {
+ let drawData={ Color:[], Angle:colorAngle };
+ if (color) drawData.Color.push(color);
+ if (color2) drawData.Color.push(color2);
+
+ let result={DrawData:null, DrawType:'DRAWGBK2'};
+ if (Array.isArray(condition))
+ {
+ drawData.Data=[];
+ for(var i in condition)
+ {
+ var item=condition[i];
+ drawData.Data[i]=item ? 1:0;
+ }
+
+ result.DrawData=drawData;
+ }
+ else
+ {
+ if (condition)
+ {
+ result.DrawData=drawData;
+ result.DrawType="DRAWGBK";
+ }
+ }
+
+ return result;
+ }
+
+ this.RGB = function (r, g, b)
+ {
+ var rgb = `rgb(${r},${g},${b})`;
+ return rgb;
+ }
+
+ this.RGBA = function (r, g, b, a)
+ {
+ var rgba = `rgba(${r},${g},${b},${a})`;
+ return rgba;
+ }
+}
+
+
+JSDraw.prototype.CalculateDrawLine=function(lineCache)
+{
+ lineCache.List=[];
+ for(let i=lineCache.Start.ID; i<=lineCache.End.ID; ++i) lineCache.List.push(i);
+
+ let height=Math.abs(lineCache.Start.Value-lineCache.End.Value);
+ let width=lineCache.List.length-1;
+
+ var result=[];
+ result.push({ID:lineCache.Start.ID, Value:lineCache.Start.Value}); //第1个点
+
+ if (lineCache.Start.Value>lineCache.End.Value)
+ {
+ for(let i=1;i0) this.MaxReqeustDataCount=option.MaxReqeustDataCount;
+ if (option.MaxRequestMinuteDayCount>0) this.MaxRequestMinuteDayCount=option.MaxRequestMinuteDayCount;
+ if (option.KLineApiUrl) this.KLineApiUrl=option.KLineApiUrl;
+ if (option.NetworkFilter) this.NetworkFilter = option.NetworkFilter;
+ }
+
+ //最新行情
+ this.GetLatestData=function()
+ {
+ if (this.LatestData) return this.Execute.RunNextJob();
+
+ var self=this;
+ wx.request({
+ url: self.RealtimeApiUrl,
+ data:
+ {
+ "field": ["name","symbol","yclose","open","price","high","low","vol","amount","date","time","increase","exchangerate","amplitude"],
+ "symbol": [this.Symbol]
+ },
+ method:"POST",
+ dataType: "json",
+ success: function (recvData)
+ {
+ self.RecvLatestData(recvData);
+ self.Execute.RunNextJob();
+ },
+ error: function(request)
+ {
+ self.RecvError(request);
+ }
+ });
+ }
+
+ this.RecvLatestData = function (recvData)
+ {
+ let data=recvData.data;
+ if (!data.stock || data.stock.length!=1) return;
+
+ let stock=data.stock[0];
+ this.LatestData={ Symbol:stock.symbol, Name:stock.name, Date:stock.date, Time:stock.time,
+ YClose:stock.yclose,Price:stock.price, Open:stock.open, High:stock.high, Low:stock.low, Vol:stock.vol, Amount:stock.amount,
+ Increase:stock.increase, Exchangerate:stock.exchangerate, Amplitude:stock.amplitude};
+
+ JSConsole.Complier.Log('[JSSymbolData::RecvLatestData]', this.LatestData);
+ }
+
+ this.GetLatestCacheData=function(dataname)
+ {
+ if (!this.LatestData) return null;
+
+ switch(dataname)
+ {
+ case DYNAINFO_ARGUMENT_ID.YCLOSE:
+ return this.LatestData.YClose;
+ case DYNAINFO_ARGUMENT_ID.OPEN:
+ return this.LatestData.Open;
+ case DYNAINFO_ARGUMENT_ID.HIGH:
+ return this.LatestData.High;
+ case DYNAINFO_ARGUMENT_ID.LOW:
+ return this.LatestData.Low;
+ case DYNAINFO_ARGUMENT_ID.VOL:
+ return this.LatestData.Vol;
+ case DYNAINFO_ARGUMENT_ID.AMOUNT:
+ return this.LatestData.Amount;
+ case DYNAINFO_ARGUMENT_ID.INCREASE:
+ return this.LatestData.Increase;
+ case DYNAINFO_ARGUMENT_ID.EXCHANGERATE:
+ return this.LatestData.Exchangerate;
+ case DYNAINFO_ARGUMENT_ID.AMPLITUDE:
+ return this.LatestData.Amplitude;
+ case DYNAINFO_ARGUMENT_ID.CLOSE:
+ return this.LatestData.Price;
+ default:
+ return null;
+ }
+ }
+
+ this.GetVolRateData = function (job, node) {
+ var volrKey = job.ID.toString() + '-VolRate-' + this.Symbol;
+ if (this.ExtendData.has(volrKey)) return this.Execute.RunNextJob();
+
+ var self = this;
+ wx.request({
+ url: self.RealtimeApiUrl,
+ data:
+ {
+ "field": ["name", "symbol", "avgvol5", 'date'],
+ "symbol": [this.Symbol]
+ },
+ method: "POST",
+ dataType: "json",
+ async: true,
+ success: function (recvData)
+ {
+ self.RecvVolRateData(recvData, volrKey);
+ self.Execute.RunNextJob();
+ },
+ error: function (request)
+ {
+ self.RecvError(request);
+ }
+ });
+ }
+
+ this.RecvVolRateData = function (recvData, key)
+ {
+ var data=recvData.data;
+ if (!data.stock || data.stock.length != 1) return;
+ var avgVol5 = data.stock[0].avgvol5;
+ var date = data.stock[0].date;
+ var item = { AvgVol5: avgVol5, Date: date };
+ this.ExtendData.set(key, item);
+
+ JSConsole.Complier.Log('[JSSymbolData::RecvVolRateData]', item);
+ }
+
+ this.GetVolRateCacheData = function (node)
+ {
+ var key = JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_VOLR_DATA.toString() + '-VolRate-' + this.Symbol;
+ if (!key || !this.ExtendData.has(key)) this.Execute.ThrowUnexpectedNode(node, '不支持VOLR');
+
+ var result = [];
+ var value = this.ExtendData.get(key);
+ var avgVol5 = value.AvgVol5 / 241;
+ var totalVol = 0;
+ //5日成交总量只取了最新一天的,历史的暂时没有取,所以数据计算的时候只计算最新的一天, 其他都空
+ for (var i = 0, j = 0; i < this.Data.Data.length; ++i)
+ {
+ result[i] = null;
+ var item = this.Data.Data[i];
+ var dateTime = item.DateTime; //日期加时间
+ if (!dateTime) continue;
+ var aryValue = dateTime.split(' ');
+ if (aryValue.length != 2) continue;
+ var date = parseInt(aryValue[0]);
+ if (date != value.Date) continue;
+
+ totalVol += item.Vol;
+ if (avgVol5 > 0) result[i] = totalVol / (j + 1) / avgVol5 * 100;
+ ++j;
+ }
+
+ return result;
+ }
+
+ //获取大盘指数数据
+ this.GetIndexData=function()
+ {
+ if (this.IndexData) return this.Execute.RunNextJob();
+
+ var self=this;
+ if (JSCommonData.ChartData.IsDayPeriod(this.Period,true)) //请求日线数据
+ {
+ wx.request({
+ url: self.KLineApiUrl,
+ data:
+ {
+ "field": ["name", "symbol", "yclose", "open", "price", "high", "low", "vol", 'up', 'down', 'stop', 'unchanged'],
+ "symbol": '000001.sh',
+ "start": -1,
+ "count": self.MaxReqeustDataCount+500 //多请求2年的数据 确保股票剔除停牌日期以后可以对上
+ },
+ method: 'POST',
+ dataType: "json",
+ success: function (recvData)
+ {
+ self.RecvIndexHistroyData(recvData);
+ self.Execute.RunNextJob();
+ },
+ error: function(request)
+ {
+ self.RecvError(request);
+ }
+ });
+ }
+ else if (JSCommonData.ChartData.IsMinutePeriod(this.Period, true)) //请求分钟数据
+ {
+ wx.request({
+ url: self.MinuteKLineApiUrl,
+ data:
+ {
+ "field": ["name","symbol","yclose","open","price","high","low","vol"],
+ "symbol": '000001.sh',
+ "start": -1,
+ "count": self.MaxRequestMinuteDayCount+5
+ },
+ method: 'POST',
+ dataType: "json",
+ success: function (data)
+ {
+ self.RecvIndexMinuteHistroyData(data);
+ self.Execute.RunNextJob();
+ },
+ error: function(request)
+ {
+ self.RecvError(request);
+ }
+ });
+ }
+ }
+
+ this.RecvIndexHistroyData=function(recvData)
+ {
+ let data = recvData.data;
+ JSConsole.Complier.Log('[JSSymbolData::RecvIndexHistroyData] recv data' , data);
+
+ let hisData=this.JsonDataToHistoryData(data);
+ this.IndexData = new JSCommonData.ChartData();
+ this.IndexData.DataType=0; /*日线数据 */
+ this.IndexData.Data=hisData;
+
+ var aryOverlayData = this.SourceData.GetOverlayData(this.IndexData.Data); //和主图数据拟合以后的数据
+ this.IndexData.Data=aryOverlayData;
+
+ if (JSCommonData.ChartData.IsDayPeriod(this.Period, false)) //周期数据
+ {
+ let periodData=this.IndexData.GetPeriodData(this.Period);
+ this.IndexData.Data=periodData;
+ }
+ }
+
+ this.RecvIndexMinuteHistroyData = function (recvData)
+ {
+ let data = recvData.data;
+ JSConsole.Complier.Log('[JSSymbolData::RecvIndexMinuteHistroyData] recv data' , data);
+
+ let hisData=this.JsonDataToMinuteHistoryData(data);
+ this.IndexData = new JSCommonData.ChartData();
+ this.IndexData.DataType=1; /*分钟线数据 */
+ this.IndexData.Data=hisData;
+
+ if (JSCommonData.ChartData.IsMinutePeriod(this.Period, false)) //周期数据
+ {
+ let periodData=this.IndexData.GetPeriodData(this.Period);
+ this.IndexData.Data=periodData;
+ }
+ }
+
+ //获取大盘指数缓存数据
+ this.GetIndexCacheData=function(dataName)
+ {
+ if (!this.IndexData) return new Array();
+
+ switch(dataName)
+ {
+ case 'INDEXA':
+ return this.IndexData.GetAmount();
+ case 'INDEXC':
+ return this.IndexData.GetClose();
+ case 'INDEXH':
+ return this.IndexData.GetHigh();
+ case 'INDEXL':
+ return this.IndexData.GetLow();
+ case 'INDEXO':
+ return this.IndexData.GetOpen();
+ case 'INDEXV':
+ return this.IndexData.GetVol();
+ case 'INDEXADV':
+ return this.IndexData.GetUp();
+ case 'INDEXDEC':
+ return this.IndexData.GetDown();
+ }
+ }
+
+ //分钟涨幅股票个数统计数据下载
+ this.GetIndexIncreaseData = function (job)
+ {
+ var upKey = job.ID.toString() + '-UpCount-' + job.Symbol;
+ var downKey = job.ID.toString() + '-DownCount-' + job.Symbol;
+ if (this.ExtendData.has(upKey) && this.ExtendData.has(downKey)) return this.Execute.RunNextJob();
+
+ var symbol = job.Symbol;
+ symbol = symbol.replace('.CI', '.ci');
+ var self = this;
+ var apiUrl = g_JSComplierResource.CacheDomain + '/cache/analyze/increaseanalyze/' + symbol + '.json';
+ JSConsole.Complier.Log('[JSSymbolData::GetIndexIncreaseData] Get url=', apiUrl);
+ wx.request({
+ url: apiUrl,
+ method: "GET",
+ dataType: "json",
+ success: function (data)
+ {
+ self.RecvMinuteIncreaseData(data, { UpKey: upKey, DownKey: downKey });
+ self.Execute.RunNextJob();
+ },
+ error: function (request)
+ {
+ self.RecvError(request);
+ }
+ });
+ }
+
+ this.RecvMinuteIncreaseData = function (recvData, key)
+ {
+ JSConsole.Complier.Log('[JSSymbolData::RecvMinuteIncreaseData] recv data', recvData);
+ var data=recvData.data;
+ if (!data.minute) return;
+ var minuteData = data.minute;
+ if (!minuteData.time || !minuteData.up || !minuteData.down) return;
+ var upData = [], downData = [];
+ for (var i = 0; i < minuteData.time.length; ++i) {
+ upData[i] = minuteData.up[i];
+ downData[i] = minuteData.down[i];
+ }
+
+ this.ExtendData.set(key.UpKey, upData);
+ this.ExtendData.set(key.DownKey, downData);
+ }
+
+ //分钟涨幅股票个数统计数据
+ this.GetIndexIncreaseCacheData = function (funcName, symbol, node) {
+ var key;
+ if (funcName == 'UPCOUNT') key = JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_INDEX_INCREASE_DATA.toString() + '-UpCount-' + symbol;
+ else if (funcName == 'DOWNCOUNT') key = JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_INDEX_INCREASE_DATA.toString() + '-DownCount-' + symbol;
+
+ if (!key || !this.ExtendData.has(key)) this.Execute.ThrowUnexpectedNode(node, '不支持函数' + funcName + '(' + symbol + ')');
+
+ return this.ExtendData.get(key);
+ }
+
+ this.GetSymbolData=function()
+ {
+ if (this.Data) return this.Execute.RunNextJob();
+
+ let self=this;
+
+ if (this.DataType === 2) //当天分钟数据
+ {
+ wx.request({
+ url: self.RealtimeApiUrl,
+ data:
+ {
+ "field": ["name", "symbol", "yclose", "open", "price", "high", "low", "vol", "amount", "date", "minute", "time", "minutecount"],
+ "symbol": [self.Symbol],
+ "start": -1
+ },
+ method: 'POST',
+ dataType: "json",
+ async: true,
+ success: function (recvData) {
+ self.RecvMinuteData(recvData);
+ self.Execute.RunNextJob();
+ }
+ });
+ return;
+ }
+
+ if (JSCommonData.ChartData.IsDayPeriod(this.Period,true)) //请求日线数据
+ {
+ wx.request({
+ url: self.KLineApiUrl,
+ data:
+ {
+ "field": [ "name", "symbol","yclose","open","price","high","low","vol"],
+ "symbol": self.Symbol,
+ "start": -1,
+ "count": self.MaxReqeustDataCount
+ },
+ method: 'POST',
+ dataType: "json",
+ async:true,
+ success: function (recvData)
+ {
+ self.RecvHistroyData(recvData);
+ self.Execute.RunNextJob();
+ },
+ error: function(request)
+ {
+ self.RecvError(request);
+ }
+ });
+ }
+ else if (JSCommonData.ChartData.IsMinutePeriod(this.Period, true)) //请求分钟数据
+ {
+ wx.request({
+ url: this.MinuteKLineApiUrl,
+ data:
+ {
+ "field": ["name","symbol","yclose","open","price","high","low","vol"],
+ "symbol": self.Symbol,
+ "start": -1,
+ "count": self.MaxRequestMinuteDayCount
+ },
+ method: 'POST',
+ dataType: "json",
+ async:true,
+ success: function (data)
+ {
+ self.RecvMinuteHistroyData(data);
+ self.Execute.RunNextJob();
+ },
+ error: function(request)
+ {
+ self.RecvError(request);
+ }
+ });
+ }
+ }
+
+ this.RecvHistroyData=function(recvData)
+ {
+ let data=recvData.data;
+ JSConsole.Complier.Log('[JSSymbolData::RecvHistroyData] recv data' , data);
+
+ let hisData=this.JsonDataToHistoryData(data);
+ this.Data=new JSCommonData.ChartData();
+ this.Data.DataType=0; /*日线数据 */
+ this.Data.Data=hisData;
+ this.SourceData = new JSCommonData.ChartData;
+ this.SourceData.Data = hisData;
+
+ if (this.Right>0) //复权
+ {
+ let rightData=this.Data.GetRightDate(this.Right);
+ this.Data.Data=rightData;
+ }
+
+ if (JSCommonData.ChartData.IsDayPeriod(this.Period, false)) //周期数据
+ {
+ let periodData=this.Data.GetPeriodData(this.Period);
+ this.Data.Data=periodData;
+ }
+
+ this.Name = data.name;
+ }
+
+ this.RecvMinuteHistroyData = function (recvData)
+ {
+ let data = recvData.data;
+ JSConsole.Complier.Log('[JSSymbolData::RecvMinuteHistroyData] recv data' , data);
+
+ let hisData=this.JsonDataToMinuteHistoryData(data);
+ this.Data = new JSCommonData.ChartData();
+ this.Data.DataType=1; /*分钟线数据 */
+ this.Data.Data=hisData;
+ this.SourceData = new JSCommonData.ChartData;
+ this.SourceData.Data = hisData;
+
+ if (JSCommonData.ChartData.IsMinutePeriod(this.Period, false)) //周期数据
+ {
+ let periodData=this.Data.GetPeriodData(this.Period);
+ this.Data.Data=periodData;
+ }
+
+ this.Name = data.name;
+ }
+
+ //最新的分钟数据走势图
+ this.RecvMinuteData = function (recvData)
+ {
+ let data = recvData.data;
+ JSConsole.Complier.Log('[JSSymbolData::RecvMinuteData] recv data', data);
+
+ var aryMinuteData = this.JsonDataToMinuteData(data);
+ this.Data = new JSCommonData.ChartData();
+ this.Data.DataType = 2; /*分钟走势图数据 */
+ this.Data.Data = aryMinuteData;
+
+ this.Name = data.stock[0].name;
+ }
+
+ this.GetSymbolCacheData=function(dataName)
+ {
+ if (!this.Data) return new Array();
+
+ switch(dataName)
+ {
+ case 'CLOSE':
+ case 'C':
+ return this.Data.GetClose();
+ case 'VOL':
+ case 'V':
+ return this.Data.GetVol();
+ case 'OPEN':
+ case 'O':
+ return this.Data.GetOpen();
+ case 'HIGH':
+ case 'H':
+ return this.Data.GetHigh();
+ case 'LOW':
+ case 'L':
+ return this.Data.GetLow();
+ case 'AMOUNT':
+ case 'AMO':
+ return this.Data.GetAmount();
+ case 'VOLINSTK':
+ return this.Data.GetPosition();
+ }
+ }
+
+ this.GetCurrBarsCount=function()
+ {
+ if (!this.Data || !this.Data.Data || !this.Data.Data.length) return new Array();
+
+ let lCount=this.Data.Data.length;
+ let result=[];
+ for(let i=lCount-1;i>=0;--i)
+ result.push(i);
+
+ return result;
+ }
+
+ this.GetIsLastBar = function ()
+ {
+ let result = [];
+ if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result
+
+ let lCount = this.Data.Data.length;
+ for (let i = 0; i < lCount; ++i)
+ {
+ if (i == lCount - 1) result.push(1);
+ else result.push(0);
+ }
+
+ return result;
+ }
+
+ //融资融券函数
+ this.GetMarginCacheData = function (id, node)
+ {
+ let jobID = JS_EXECUTE_JOB_ID.GetMarginJobID(id);
+ if (!jobID) this.Execute.ThrowUnexpectedNode(node, '不支持MARGIN(' + id + ')');
+ if (this.MarginData.has(jobID)) return this.MarginData.get(jobID);
+
+ return [];
+ }
+
+ //下融资融券
+ this.GetMarginData = function (jobID)
+ {
+ if (this.MarginData.has(jobID)) return this.Execute.RunNextJob();
+
+ JSConsole.Complier.Log('[JSSymbolData::GetMarginData] jobID=', jobID);
+ var self = this;
+ let fieldList = ["name", "date", "symbol"];
+
+ switch (jobID)
+ {
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BALANCE: //融资融券余额
+ fieldList.push("margin.balance");
+ break;
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_RATE: //融资占比
+ fieldList.push("margin.rate");
+ break;
+
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_BALANCE: //买入信息-融资余额
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_AMOUNT: //买入信息-买入额
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_REPAY: //买入信息-偿还额
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_NET: //买入信息-融资净买入
+ fieldList.push("margin.buy");
+ break;
+
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_BALANCE: //卖出信息-融券余量
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_VOLUME: //卖出信息-卖出量
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_REPAY: //卖出信息-偿还量
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_NET: //卖出信息-融券净卖出
+ fieldList.push("margin.sell");
+ break;
+ }
+
+ //请求数据
+ wx.request({
+ url: this.StockHistoryDayApiUrl,
+ data:
+ {
+ "field": fieldList,
+ "symbol": [this.Symbol],
+ "orderfield": "date"
+ },
+ method: 'POST',
+ dataType: "json",
+ async: true,
+ success: function (recvData) {
+ self.RecvMarginData(recvData, jobID);
+ self.Execute.RunNextJob();
+ }
+ });
+ }
+
+ this.RecvMarginData = function (recvData, jobID)
+ {
+ var data = recvData.data;
+ //JSConsole.Complier.Log(data);
+ if (!data.stock || data.stock.length != 1) return;
+
+ let stock = data.stock[0];
+ var aryData = new Array();
+ var aryData2 = [], aryData3 = [], aryData4 = []; //其他3个数据
+ for (let i in stock.stockday)
+ {
+ var item = stock.stockday[i];
+ var marginData = item.margin;
+ if (!marginData) continue;
+
+ let indexData = new JSCommonData.SingleData();
+ indexData.Date = item.date;
+
+ switch (jobID)
+ {
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BALANCE:
+ if (!this.IsNumber(marginData.balance)) continue;
+ indexData.Value = marginData.balance; //融资融券余额
+ aryData.push(indexData);
+ break;
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_RATE:
+ if (!this.IsNumber(marginData.rate)) continue;
+ indexData.Value = marginData.rate; //融资占比
+ aryData.push(indexData);
+ break;
+
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_BALANCE: //买入信息-融资余额
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_AMOUNT: //买入信息-买入额
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_REPAY: //买入信息-偿还额
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_NET: //买入信息-融资净买入
+ var buyData = marginData.buy;
+ if (!buyData) continue;
+ if (!this.IsNumber(buyData.balance) || !this.IsNumber(buyData.amount) || !this.IsNumber(buyData.repay) || !this.IsNumber(buyData.net)) continue;
+
+ indexData.Value = buyData.balance;
+ var indexData2 = new JSCommonData.SingleData();
+ indexData2.Date = item.date;
+ indexData2.Value = buyData.amount;
+ var indexData3 = new JSCommonData.SingleData();
+ indexData3.Date = item.date;
+ indexData3.Value = buyData.repay;
+ var indexData4 = new JSCommonData.SingleData();
+ indexData4.Date = item.date;
+ indexData4.Value = buyData.net;
+
+ aryData.push(indexData);
+ aryData2.push(indexData2);
+ aryData3.push(indexData3);
+ aryData4.push(indexData4);
+ break;
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_BALANCE: //卖出信息-融券余量
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_VOLUME: //卖出信息-卖出量
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_REPAY: //卖出信息-偿还量
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_NET: //卖出信息-融券净卖出
+ var sellData = marginData.sell;
+ if (!sellData) continue;
+ if (!this.IsNumber(sellData.balance) || !this.IsNumber(sellData.volume) || !this.IsNumber(sellData.repay) || !this.IsNumber(sellData.net)) continue;
+
+ indexData.Value = buyData.balance;
+ var indexData2 = new JSCommonData.SingleData();
+ indexData2.Date = item.date;
+ indexData2.Value = buyData.volume;
+ var indexData3 = new JSCommonData.SingleData();
+ indexData3.Date = item.date;
+ indexData3.Value = buyData.repay;
+ var indexData4 = new JSCommonData.SingleData();
+ indexData4.Date = item.date;
+ indexData4.Value = buyData.net;
+
+ aryData.push(indexData);
+ aryData2.push(indexData2);
+ aryData3.push(indexData3);
+ aryData4.push(indexData4);
+ break;
+ default:
+ continue;
+ }
+ }
+
+ var allData = [];
+ if (jobID === JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BALANCE || jobID === JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_RATE)
+ {
+ allData.push({ JobID: jobID, Data: aryData });
+ }
+ else if (jobID === JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_BALANCE || jobID === JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_AMOUNT ||
+ jobID === JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_REPAY || jobID === JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_NET)
+ {
+ allData.push({ JobID: JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_BALANCE, Data: aryData });
+ allData.push({ JobID: JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_AMOUNT, Data: aryData2 });
+ allData.push({ JobID: JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_REPAY, Data: aryData3 });
+ allData.push({ JobID: JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_NET, Data: aryData4 });
+ }
+ else if (jobID === JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_BALANCE || jobID === JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_VOLUME ||
+ jobID === JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_REPAY || jobID === JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_NET)
+ {
+ allData.push({ JobID: JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_BALANCE, Data: aryData });
+ allData.push({ JobID: JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_VOLUME, Data: aryData2 });
+ allData.push({ JobID: JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_REPAY, Data: aryData3 });
+ allData.push({ JobID: JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_NET, Data: aryData4 });
+ }
+
+ for (let i in allData)
+ {
+ let aryFixedData = this.Data.GetFittingData(allData[i].Data);
+
+ var bindData = new JSCommonData.ChartData();
+ bindData.Data = aryFixedData;
+ bindData.Period = this.Period; //周期
+
+ if (bindData.Period > 0) //周期数据
+ {
+ var periodData = bindData.GetPeriodSingleData(bindData.Period);
+ bindData.Data = periodData;
+ }
+
+ let data = bindData.GetValue();
+ this.MarginData.set(allData[i].JobID, data);
+ }
+ }
+
+ this.GetNewsAnalysisCacheData = function (id, node)
+ {
+
+ let jobID = JS_EXECUTE_JOB_ID.GetNewsAnalysisID(id);
+ if (!jobID) this.Execute.ThrowUnexpectedNode(node, '不支持NEWS(' + id + ')');
+ if (this.NewsAnalysisData.has(jobID)) return this.NewsAnalysisData.get(jobID);
+
+ return [];
+ }
+
+ //下载新闻统计
+ this.GetNewsAnalysisData = function (jobID)
+ {
+ if (this.NewsAnalysisData.has(jobID)) return this.Execute.RunNextJob();
+
+ var self = this;
+ var mapFolder = new Map([
+ [JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_NEGATIVE, "negative"],
+ [JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_RESEARCH, 'research'],
+ [JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_INTERACT, 'interact'],
+ [JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE, 'holderchange'], //NEWS(4) 股东增持
+ [JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE2, 'holderchange'], //NEWS(5) 股东减持
+ [JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_TRUSTHOLDER, 'trustholder'], //NEWS(6) 信托持股
+ [JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_BLOCKTRADING, 'Blocktrading'], //NEWS(7) 大宗交易
+ [JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_COMPANYNEWS, 'companynews'], //NEWS(8) 官网新闻
+ [JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_TOPMANAGERS, 'topmanagers'], //NEWS(9) 高管要闻
+ [JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_PLEDGE, 'Pledge'], //NEWS(10) 股权质押
+ ]);
+
+ if (!mapFolder.has(jobID))
+ {
+ this.Execute.RunNextJob();
+ return;
+ }
+
+ var folderName = mapFolder.get(jobID);
+ var url = this.StockNewsAnalysisApiUrl + '/' + folderName + '/' + this.Symbol + '.json';
+
+ //请求数据
+ wx.request({
+ url: url,
+ method: 'GET',
+ dataType: "json",
+ async: true,
+ success: function (recvData)
+ {
+ if (recvData.statusCode==200)
+ self.RecvNewsAnalysisData(recvData, jobID);
+ else
+ self.RecvNewsAnalysisDataError(recvData, jobID);
+ self.Execute.RunNextJob();
+ },
+ fail: function (request, textStatus)
+ {
+ //self.RecvNewsAnalysisDataError(request, textStatus, jobID);
+ self.Execute.RunNextJob();
+ }
+ });
+ }
+
+ this.RecvNewsAnalysisDataError = function (recvData, jobID)
+ {
+ JSConsole.Complier.Log('[JSSymbolData::RecvNewsAnalysisDataError] request error.', recvData.statusCode);
+
+ //没有新闻使用0数据填充
+ var aryData = [];
+ for (var i = 0; i < this.Data.Data.length; ++i)
+ {
+ var item = new JSCommonData.SingleData();
+ item.Date = this.Data.Data[i].Date;
+ item.Value = 0
+ aryData.push(item);
+ }
+
+ var bindData = new JSCommonData.ChartData();
+ bindData.Data = aryData;
+ this.NewsAnalysisData.set(jobID, bindData.GetValue());
+ }
+
+ this.RecvNewsAnalysisData = function (recvData, jobID)
+ {
+ var data=recvData.data;
+ if (!data.data || !data.date) return;
+ if (data.data.length <= 0 || data.data.length != data.date.length) return;
+
+ JSConsole.Complier.Log('[JSSymbolData::RecvNewsAnalysisData] jobID', jobID, data.update);
+ if (jobID == JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE || jobID == JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE2)
+ {
+ var aryData = [], aryData2 = [];
+ for (var i = 0; i < data.data.length; ++i)
+ {
+ var item = new JSCommonData.SingleData();
+ item.Date = data.date[i];
+ item.Value = data.data[i];
+ if (this.IsNumber(item.Value)) aryData.push(item);
+
+ if (i < data.data2.length)
+ {
+ item = new JSCommonData.SingleData();
+ item.Date = data.date[i];
+ item.Value = data.data2[i];
+ if (this.IsNumber(item.Value)) aryData2.push(item);
+ }
+ }
+
+ let aryFixedData = this.Data.GetFittingData2(aryData, 0);
+ var bindData = new JSCommonData.ChartData();
+ bindData.Data = aryFixedData;
+ this.NewsAnalysisData.set(JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE, bindData.GetValue());
+
+ aryFixedData = this.Data.GetFittingData2(aryData2, 0);
+ bindData = new JSCommonData.ChartData();
+ bindData.Data = aryFixedData;
+ this.NewsAnalysisData.set(JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE2, bindData.GetValue());
+ }
+ else
+ {
+ var aryData = [];
+ for (var i = 0; i < data.data.length; ++i)
+ {
+ var item = new JSCommonData.SingleData();
+ item.Date = data.date[i];
+ item.Value = data.data[i];
+ aryData.push(item);
+ }
+
+ let aryFixedData = this.Data.GetFittingData2(aryData, 0);
+
+ var bindData = new JSCommonData.ChartData();
+ bindData.Data = aryFixedData;
+
+ this.NewsAnalysisData.set(jobID, bindData.GetValue());
+ }
+ }
+
+ this.GetStockDataKey=function(jobItem, aryArgs)
+ {
+ var key=jobItem.FunctionName;
+ if (aryArgs.length>0)
+ {
+ key+="(";
+ for(var i=0;i0) key+=",";
+ key+=aryArgs[i].toString();
+ }
+ key+=")";
+ }
+ return key;
+ }
+
+ this.GetFinOne=function(jobItem)
+ {
+ var aryArgs=this.JobArgumentsToArray(jobItem, 3);
+ var key=this.GetStockDataKey(jobItem,aryArgs);
+ if (this.StockData.has(key)) return this.Execute.RunNextJob();
+ var self=this;
+ if (this.NetworkFilter)
+ {
+ var dateRange=this.Data.GetDateRange();
+ var obj=
+ {
+ Name:'JSSymbolData::GetFinOne', //类名::
+ Explain:'财务数据FINONE(ID,Y,MMDD)',
+ JobID:jobItem.ID,
+ Request:{ Url:self.StockHistoryDayApiUrl, Type:'POST', Data:{ Args:aryArgs, symbol: this.Symbol, daterange:dateRange } },
+ Self:this,
+ PreventDefault:false
+ };
+ this.NetworkFilter(obj, function(recvData)
+ {
+ self.RecvStockValue(recvData,jobItem,key,1);
+ self.Execute.RunNextJob();
+ });
+
+ if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求
+ }
+
+ var apiDownload=new DownloadFinOneData(
+ {
+ Job:jobItem,
+ Symbol:this.Symbol,
+ Url:this.StockHistoryDayApiUrl,
+ Args:aryArgs,
+ DataKey:key,
+ Callback:function(recvData, jobItem, key)
+ {
+ self.RecvStockValue(recvData, jobItem, key,1);
+ self.Execute.RunNextJob();
+ },
+ ErrorCallback:function(strError)
+ {
+ self.AddStockValueError(key,strError);
+ }
+ });
+
+ apiDownload.Download();
+ }
+
+ this.GetFinValue=function(jobItem)
+ {
+ var aryArgs=this.JobArgumentsToArray(jobItem, 1);
+ var lID=aryArgs[0];
+ var key=this.GetStockDataKey(jobItem,aryArgs);
+ if (this.StockData.has(key)) return this.Execute.RunNextJob();
+ var self=this;
+ if (this.NetworkFilter)
+ {
+ var dateRange=this.Data.GetDateRange();
+ var obj=
+ {
+ Name:'JSSymbolData::GetFinValue', //类名::
+ Explain:'财务数据FINVALUE(ID)',
+ JobID:jobItem.ID,
+ Request:{ Url:self.StockHistoryDayApiUrl, Type:'POST', Data:{ id:lID, symbol: this.Symbol, daterange:dateRange } },
+ Self:this,
+ PreventDefault:false
+ };
+ this.NetworkFilter(obj, function(recvData)
+ {
+ self.RecvStockValue(recvData,jobItem,key,0);
+ self.Execute.RunNextJob();
+ });
+
+ if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求
+ }
+
+ var apiDownload=new DownloadFinValueData(
+ {
+ Job:jobItem,
+ Symbol:this.Symbol,
+ Url:this.StockHistoryDayApiUrl,
+ Args:aryArgs,
+ DataKey:key,
+ Callback:function(recvData, jobItem, key)
+ {
+ self.RecvStockValue(recvData, jobItem, key,0);
+ self.Execute.RunNextJob();
+ },
+ ErrorCallback:function(strError)
+ {
+ self.AddStockValueError(key,strError);
+ }
+ });
+
+ apiDownload.Download();
+ }
+
+
+ this.GetFinance=function(jobItem)
+ {
+ var aryArgs=this.JobArgumentsToArray(jobItem, 1);
+ var lID=aryArgs[0];
+ var key=this.GetStockDataKey(jobItem,aryArgs);
+ if (this.StockData.has(key)) return this.Execute.RunNextJob();
+
+ var self=this;
+ if (this.NetworkFilter)
+ {
+ var dateRange=this.Data.GetDateRange();
+ var obj=
+ {
+ Name:'JSSymbolData::GetFinance', //类名::
+ Explain:'财务数据FINANCE(ID)',
+ JobID:jobItem.ID,
+ Request:{ Url:self.RealtimeApiUrl, Type:'POST', Data:{ id:lID, symbol: this.Symbol, daterange:dateRange } },
+ Self:this,
+ PreventDefault:false
+ };
+ this.NetworkFilter(obj, function(recvData)
+ {
+ self.RecvStockValue(recvData,jobItem,key,0);
+ self.Execute.RunNextJob();
+ });
+
+ if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求
+ }
+
+ var apiDownload=new DownloadFinanceData(
+ {
+ Job:jobItem,
+ Symbol:this.Symbol,
+ Url:this.StockHistoryDayApiUrl,
+ RealtimeUrl:this.RealtimeApiUrl,
+ Args:aryArgs,
+ DataKey:key,
+ Callback:function(recvData, jobItem, key)
+ {
+ self.RecvStockValue(recvData, jobItem, key,0);
+ self.Execute.RunNextJob();
+ },
+ ErrorCallback:function(strError)
+ {
+ self.AddStockValueError(key,strError);
+ }
+ });
+
+ apiDownload.Download();
+ }
+
+ this.GetVariantData=function(jobItem)
+ {
+ var key=jobItem.VariantName;
+ if (this.StockData.has(key)) return this.Execute.RunNextJob();
+
+ var self=this;
+ if (this.NetworkFilter)
+ {
+ var dateRange=this.Data.GetDateRange();
+ var obj=
+ {
+ Name:'JSSymbolData::GetVariantData', //类名::
+ Explain:'变量数据下载',
+ JobID:jobItem.ID,
+ Request:{ Url:"www.121287.com", Type:'POST', Data:{ VariantName:jobItem.VariantName, symbol: this.Symbol, daterange:dateRange } },
+ Self:this,
+ PreventDefault:false
+ };
+ this.NetworkFilter(obj, function(recvData)
+ {
+ if (recvData.Error)
+ {
+ self.AddStockValueError(key,recvData.Error);
+ }
+ else
+ {
+ var dataType=0;
+ if (IFrameSplitOperator.IsNumber(recvData.DataType)) dataType=recvData.DataType;
+ self.RecvStockValue(recvData.Data,jobItem,key,dataType);
+ }
+
+ self.Execute.RunNextJob();
+ });
+
+ if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求
+ }
+
+ var errorCallback=function(strError)
+ {
+ self.AddStockValueError(key,strError);
+ };
+
+ var apiDownload;
+ if (jobItem.VariantName=="CAPITAL" || jobItem.VariantName=="TOTALCAPITAL" || jobItem.VariantName=="EXCHANGE")
+ {
+ var callback=function(recvData, jobItem, key)
+ {
+ self.RecvStockValue(recvData, jobItem, key,0);
+ self.Execute.RunNextJob();
+ };
+
+ apiDownload=new DownloadFinanceData(
+ {
+ Job:jobItem,
+ Symbol:this.Symbol,
+ Url:this.StockHistoryDayApiUrl,
+ RealtimeUrl:this.RealtimeApiUrl,
+ Args:[jobItem.VariantName],
+ DataKey:key,
+ Callback:callback,
+ ErrorCallback:errorCallback
+ });
+ }
+ else if (jobItem.VariantName=="HYBLOCK" || jobItem.VariantName=="DYBLOCK" || jobItem.VariantName=="GNBLOCK")
+ {
+ var callback=function(recvData, jobItem, key, dataType)
+ {
+ self.RecvStockValue(recvData, jobItem, key, dataType);
+ self.Execute.RunNextJob();
+ };
+
+ apiDownload=new DownloadGroupData(
+ {
+ Job:jobItem,
+ Symbol:this.Symbol,
+ Url:this.StockHistoryDayApiUrl,
+ RealtimeUrl:this.RealtimeApiUrl,
+ Args:[jobItem.VariantName],
+ DataKey:key,
+ Callback:callback,
+ ErrorCallback:errorCallback
+ });
+ }
+ else if (jobItem.VariantName=="INBLOCK")
+ {
+ var errorMessage=`${jobItem.VariantName}, 请对接外部数据.`;
+ this.AddStockValueError(key,errorMessage);
+ this.Execute.RunNextJob();
+ return;
+ }
+ else
+ {
+ var errorMessage=`不支持变量${jobItem.VariantName}, 请对接外部数据.`;
+ this.AddStockValueError(key,errorMessage);
+ this.Execute.RunNextJob();
+ return;
+ }
+
+ apiDownload.Download();
+ }
+
+ this.GetGPJYValue=function(jobItem)
+ {
+ var aryArgs=this.JobArgumentsToArray(jobItem, 3);
+ var key=this.GetStockDataKey(jobItem,aryArgs);
+ if (this.StockData.has(key)) return this.Execute.RunNextJob();
+
+ var self=this;
+ //TYPE:为1表示做平滑处理,没有数据的周期返回上一周期的值;为0表示不做平滑处理
+ var dataType=aryArgs[2]==1?0:2;
+ if (this.NetworkFilter)
+ {
+ var dateRange=this.Data.GetDateRange();
+ var obj=
+ {
+ Name:'JSSymbolData::GetGPJYValue', //类名::
+ Explain:'股票交易类数据GPJYVALUE(ID,N,TYPE)',
+ JobID:jobItem.ID,
+ Request:{ Url:self.StockHistoryDayApiUrl, Type:'POST', Data:{ Args:aryArgs, symbol: this.Symbol, daterange:dateRange } },
+ Self:this,
+ PreventDefault:false
+ };
+ this.NetworkFilter(obj, function(recvData)
+ {
+ self.RecvStockValue(recvData,jobItem,key,dataType);
+ self.Execute.RunNextJob();
+ });
+
+ if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求
+ }
+
+ var apiDownload=new DownloadGPJYValue(
+ {
+ Job:jobItem,
+ Symbol:this.Symbol,
+ Url:this.StockHistoryDayApiUrl,
+ Args:aryArgs,
+ DataKey:key,
+ Callback:function(recvData, jobItem, key)
+ {
+ self.RecvStockValue(recvData, jobItem, key,dataType);
+ self.Execute.RunNextJob();
+ },
+ ErrorCallback:function(strError)
+ {
+ self.AddStockValueError(key,strError);
+ }
+ });
+
+ apiDownload.Download();
+ }
+
+ //自定义变量数据下载
+ this.GetCustomVariantData=function(jobItem)
+ {
+ var key=jobItem.VariantName;
+ if (this.StockData.has(key)) return this.Execute.RunNextJob();
+
+ var variantInfo=g_JSComplierResource.CustomVariant.Data.get(key);
+ var self=this;
+ if (this.NetworkFilter)
+ {
+ var dateRange=this.Data.GetDateRange();
+ var obj=
+ {
+ Name:'JSSymbolData::GetCustomVariantData', //类名::函数名
+ Explain:'自定义变量数据下载',
+ JobID:jobItem.ID,
+ Request:{ Url:"www.121287.com", Type:'POST', Data:{ VariantName:jobItem.VariantName, symbol: this.Symbol, daterange:dateRange } },
+ Self:this,
+ VariantInfo:variantInfo,
+ PreventDefault:false
+ };
+ this.NetworkFilter(obj, function(recvData)
+ {
+ if (recvData.Error) self.AddStockValueError(key,recvData.Error);
+ else self.RecvStockValue(recvData.Data,jobItem,key,recvData.DataType);
+ self.Execute.RunNextJob();
+ });
+ }
+ else
+ {
+ this.AddStockValueError(key, `自定义变量${key}下载失败`);
+ this.Execute.RunNextJob();
+ }
+ }
+
+ this.GetCustomFunctionData=function(jobItem)
+ {
+ var key=jobItem.FunctionName;
+ var functionInfo=g_JSComplierResource.CustomFunction.Data.get(key);
+ if (!functionInfo.IsDownload) return this.Execute.RunNextJob();
+ if (this.StockData.has(key)) return this.Execute.RunNextJob(); //一个函数只能缓存一个数据, 保存多个外部自己保存
+
+ var self=this;
+ if (this.NetworkFilter)
+ {
+ var dateRange=this.Data.GetDateRange();
+ var obj=
+ {
+ Name:'JSSymbolData::GetCustomFunctionData', //类名::函数名
+ Explain:'自定义函数数据下载',
+ JobID:jobItem.ID,
+ Request:
+ {
+ Url:"www.121287.com", Type:'POST',
+ Data:
+ {
+ FunctionName:jobItem.FunctionName,
+ symbol: this.Symbol, daterange:dateRange,
+ JobItem:jobItem //函数编译信息
+ }
+ },
+ Self:this,
+ FunctionInfo:functionInfo,
+ PreventDefault:false
+ };
+ this.NetworkFilter(obj, function(recvData)
+ {
+ if (recvData.Error) self.AddStockValueError(key,recvData.Error);
+ else self.RecvStockValue(recvData.Data,jobItem,key,recvData.DataType);
+ self.Execute.RunNextJob();
+ });
+ }
+ else
+ {
+ this.AddStockValueError(key, `自定义函数${key}下载失败`);
+ this.Execute.RunNextJob();
+ }
+ }
+
+ this.RecvStockValue=function(recvData,jobItem,key,dataType)
+ {
+ if (!recvData)
+ {
+ //JSConsole.Complier.Log(`[JSSymbolData::RecvStockValue] key=${key} data is null`);
+ return;
+ }
+
+ if (dataType==0)
+ {
+ if (Array.isArray(recvData))
+ {
+ var kdata=this.Data; //K线
+ var aryFittingData;
+ if (JSCommonData.ChartData.IsDayPeriod(this.Period,true))
+ aryFittingData=kdata.GetFittingFinanceData(recvData); //数据和主图K线拟合
+ else if (JSCommonData.ChartData.IsMinutePeriod(this.Period,true))
+ aryFittingData=kdata.GetMinuteFittingFinanceData(recvData); //数据和主图K线拟合
+ else
+ return;
+
+ var bindData=new JSCommonData.ChartData();
+ bindData.Data=aryFittingData;
+ var result=bindData.GetValue();
+
+ if (key=="EXCHANGE") //计算换手率=成交量/流通股本*100
+ {
+ for(var i in result)
+ {
+ var kitem=kdata.Data[i];
+ if (result[i]>0)
+ result[i]=kitem.Vol/result[i] * 100;
+ }
+ }
+
+ this.StockData.set(key,{ Data:result });
+ }
+ else
+ {
+ this.StockData.set(key,{ Data:recvData.Value });
+ }
+ }
+ else if (dataType==1) //单数值
+ {
+ this.StockData.set(key,{ Data:recvData.Value });
+ }
+ else if (dataType==2) //数据不做平滑处理
+ {
+ var kdata=this.Data; //K线
+ var aryFittingData;
+ if (JSCommonData.ChartData.IsDayPeriod(this.Period,true))
+ aryFittingData=kdata.GetFittingTradeData(recvData, 0, false); //数据和主图K线拟合
+ else if (JSCommonData.ChartData.IsMinutePeriod(this.Period,true))
+ aryFittingData=kdata.GetMinuteFittingTradeData(recvData, 0, false); //数据和主图K线拟合
+ else
+ return;
+
+ var bindData=new JSCommonData.ChartData();
+ bindData.Data=aryFittingData;
+ var result=bindData.GetValue();
+
+ this.StockData.set(key,{ Data:result });
+ }
+ }
+
+ this.AddStockValueError=function(key, message)
+ {
+ this.StockData.set(key,{ Error:message });
+ }
+
+ this.GetStockCacheData=function(obj)
+ {
+ var key;
+ if (obj.FunctionName)
+ key=this.GetStockDataKey({FunctionName:obj.FunctionName}, obj.Args);
+ else if (obj.VariantName)
+ key=obj.VariantName;
+ else if (obj.CustomName)
+ key=obj.CustomName; //自定义名字
+ else
+ return null;
+
+ if (!this.StockData.has(key)) return null;
+ var data=this.StockData.get(key);
+
+ if (data.Error) this.Execute.ThrowUnexpectedNode(obj.Node, data.Error);
+ return data.Data;
+ }
+
+ this.IsInBlock=function(blockName, node)
+ {
+ var data=this.GetStockCacheData({ VariantName:"INBLOCK", Node:node });
+ if (!data) return 0;
+ var aryBlock=data.split('|');
+ for(var i=0; i up) item.Up = list[i][up];
+ if (list[i].length > down) item.Down = list[i][down];
+ if (list[i].length > stop) item.Stop = list[i][stop];
+ if (list[i].length > unchanged) item.Unchanged = list[i][unchanged];
+
+ aryDayData.push(item);
+ }
+
+ return aryDayData;
+ }
+
+ this.JsonDataToMinuteHistoryData=function(data)
+ {
+ var list = data.data;
+ var aryDayData=new Array();
+ var date = 0, yclose = 1, open = 2, high = 3, low = 4, close = 5, vol = 6, amount = 7, time = 8;
+ for (var i = 0; i < list.length; ++i)
+ {
+ let item = new JSCommonData.HistoryData();
+
+ item.Date = list[i][date];
+ item.Open = list[i][open];
+ item.YClose = list[i][yclose];
+ item.Close = list[i][close];
+ item.High = list[i][high];
+ item.Low = list[i][low];
+ item.Vol = list[i][vol]; //原始单位股
+ item.Amount = list[i][amount];
+ item.Time=list[i][time];
+
+ // if (isNaN(item.Open) || item.Open<=0) continue; //停牌的数据剔除
+ aryDayData.push(item);
+ }
+
+ // 无效数据处理
+ for(let i = 0; i < aryDayData.length; ++i)
+ {
+ var minData = aryDayData[i];
+ if (minData == null) coninue;
+ if (isNaN(minData.Open) || minData.Open <= 0 || isNaN(minData.High) || minData.High <= 0 || isNaN(minData.Low) || minData.Low <= 0
+ || isNaN(minData.Close) || minData.Close <= 0 || isNaN(minData.YClose) || minData.YClose <= 0)
+ {
+ if (i == 0)
+ {
+ if (minData.YClose > 0)
+ {
+ minData.Open = minData.YClose;
+ minData.High = minData.YClose;
+ minData.Low = minData.YClose;
+ minData.Close = minData.YClose;
+ }
+ }
+ else // 用前一个有效数据填充
+ {
+ for(let j = i-1; j >= 0; --j)
+ {
+ var minData2 = aryDayData[j];
+ if (minData2 == null) coninue;
+ if (minData2.Open > 0 && minData2.High > 0 && minData2.Low > 0 && minData2.Close > 0)
+ {
+ if (minData.YClose <= 0) minData.YClose = minData2.Close;
+ minData.Open = minData2.Open;
+ minData.High = minData2.High;
+ minData.Low = minData2.Low;
+ minData.Close = minData2.Close;
+ break;
+ }
+ }
+ }
+ }
+ }
+ return aryDayData;
+ }
+
+ //API 返回数据 转化为array[]
+ this.JsonDataToMinuteData = function (data)
+ {
+ var aryMinuteData = new Array();
+ for (var i in data.stock[0].minute)
+ {
+ var jsData = data.stock[0].minute[i];
+ var item = new JSCommonData.MinuteData();
+
+ item.Close = jsData.price;
+ item.Open = jsData.open;
+ item.High = jsData.high;
+ item.Low = jsData.low;
+ item.Vol = jsData.vol; //股
+ item.Amount = jsData.amount;
+ if (i == 0) //第1个数据 写死9:25
+ item.DateTime = data.stock[0].date.toString() + " 0925";
+ else
+ item.DateTime = data.stock[0].date.toString() + " " + jsData.time.toString();
+ item.Date = data.stock[0].date;
+ item.Time = jsData.time;
+ item.Increate = jsData.increate;
+ item.Risefall = jsData.risefall;
+ item.AvPrice = jsData.avprice;
+
+ aryMinuteData[i] = item;
+ }
+
+ return aryMinuteData;
+ }
+
+ //CODELIKE 模糊股票代码
+ this.CODELIKE=function(value)
+ {
+ if (this.Symbol.indexOf(value)==0) return 1;
+
+ return 0;
+ }
+
+ this.NAMELIKE = function (value)
+ {
+ if (this.Name && this.Name.indexOf(value) == 0) return 1;
+ return 0;
+ }
+
+ /*
+ SETCODE 市场类型
+ 0:深圳 1:上海,47:中金所期货 28:郑州商品 29:大连商品 30:上海商品,27:香港指数 31:香港主板,48:香港创业板...
+ */
+ this.SETCODE=function()
+ {
+ if (this.Symbol.indexOf('.sh')) return 1;
+ if (this.Symbol.indexOf('.sz')) return 0;
+
+ return 0;
+ }
+
+ this.GetSymbol = function () { return this.Symbol; }
+
+ this.GetName = function () { return this.Name; }
+
+ this.TIME=function()
+ {
+ var result = [];
+ if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result;
+
+ for(let i in this.Data.Data)
+ {
+ var item=this.Data.Data[i];
+ if (this.IsNumber(item.Time))
+ result[i]=item.Time;
+ else
+ result[i]=0;
+ }
+
+ return result;
+ }
+
+ this.DATE = function ()
+ {
+ var result = [];
+ if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result;
+
+ for (let i in this.Data.Data)
+ {
+ var item = this.Data.Data[i];
+ result[i] = item.Date - 19000000;;
+ }
+
+ return result;
+ }
+
+ this.YEAR = function ()
+ {
+ var result = [];
+ if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result;
+
+ for (let i in this.Data.Data)
+ {
+ var item = this.Data.Data[i];
+ if (this.IsNumber(item.Date))
+ result[i] = parseInt(item.Date / 10000);
+ else
+ result[i] = null;
+ }
+
+ return result;
+ }
+
+ this.MONTH = function ()
+ {
+ var result = [];
+ if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result;
+
+ for (let i in this.Data.Data)
+ {
+ var item = this.Data.Data[i];
+ if (this.IsNumber(item.Date))
+ result[i] = parseInt(item.Date % 10000 / 100);
+ else
+ result[i] = null;
+ }
+
+ return result;
+ }
+
+ //星期 1-7
+ this.WEEK = function ()
+ {
+ var result = [];
+ if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result;
+
+ var tempDate = new Date();
+ for (let i in this.Data.Data)
+ {
+ var item = this.Data.Data[i];
+ result[i] = null;
+ if (!this.IsNumber(item.Date)) continue;
+
+ var year = parseInt(item.Date / 10000);
+ var month = parseInt(item.Date % 10000 / 100);
+ var day = item.Date % 100;
+
+ tempDate.setFullYear(year);
+ tempDate.setMonth(month - 1);
+ tempDate.setDate(day);
+
+ result[i] = tempDate.getDay();
+ }
+
+ return result;
+ }
+
+ this.REFDATE = function (data, date)
+ {
+ var result = null;
+
+ var findDate=null;
+ if (Array.isArray(date))
+ {
+ if (date.length>0) findDate=date[date.length-1];
+ }
+ else if (this.IsNumber(date))
+ {
+ findDate=date;
+ }
+ if (findDate==null) return null;
+ if (findDate<5000000) findDate+=19000000;
+
+ var index = null;
+ for (let i in this.Data.Data) //查找日期对应的索引
+ {
+ if (this.Data.Data[i].Date == findDate)
+ {
+ index = parseInt(i);
+ break;
+ }
+ }
+
+ if (index == null || index >= data.length) return null;
+
+ return data[index];
+ }
+
+ //用法:结果从0到11,依次分别是1/5/15/30/60分钟,日/周/月,多分钟,多日,季,年
+ this.PERIOD=function()
+ {
+ //Period周期 0=日线 1=周线 2=月线 3=年线 9=季线 4=1分钟 5=5分钟 6=15分钟 7=30分钟 8=60分钟
+ const PERIOD_MAP=[5,6,7,11, 0,1,2,3,4,5, 9];
+ if (this.Period >= 0 && this.Period <= PERIOD_MAP.length - 1)
+ return PERIOD_MAP[this.Period];
+
+ return this.Period;
+ }
+
+ this.GetDrawNull = function ()
+ {
+ var result = [];
+ if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result;
+
+ for (let i in this.Data.Data)
+ {
+ result[i] = null;
+ }
+
+ return result;
+ }
+}
+
+//是否有是有效的数字
+JSSymbolData.prototype.IsNumber = function (value)
+{
+ if (value == null) return false;
+ if (isNaN(value)) return false;
+
+ return true;
+}
+
+JSSymbolData.prototype.IsDivideNumber = function (value)
+{
+ if (value == null) return false;
+ if (isNaN(value)) return false;
+ if (value == 0) return false;
+
+ return true;
+}
+
+JSSymbolData.prototype.JsonDataToFinance = function (data)
+ {
+ var financeData;
+
+ for (let i = 1; i <= 4; ++i)
+ {
+ switch (i)
+ {
+ case 1:
+ var finance = data.finance1;
+ var announcement = data.announcement1;
+ break;
+ case 2:
+ var finance = data.finance2;
+ var announcement = data.announcement2;
+ break;
+ case 3:
+ var finance = data.finance3;
+ var announcement = data.announcement3;
+ break;
+ case 4:
+ var finance = data.finance4;
+ var announcement = data.announcement4;
+ break;
+ default:
+ break;
+ }
+
+ if (!finance || !announcement || !this.IsNumber(announcement.year) || !this.IsNumber(announcement.quarter)) continue;
+ if (financeData) //如果存在1天公布多个报告期数据 只取最新的一个公告期数据
+ {
+ if (financeData.Announcement.year < announcement.year)
+ financeData = { Date: item.date, Finance: finance, Announcement: announcement };
+ }
+ else
+ {
+ financeData = { Date: data.date, Finance: finance, Announcement: announcement };
+ }
+
+ }
+
+ return financeData;
+}
+
+var JS_EXECUTE_DEBUG_LOG=false;
+
+var JS_EXECUTE_JOB_ID=
+{
+ JOB_DOWNLOAD_SYMBOL_DATA:1, //下载股票的K线数据
+ JOB_DOWNLOAD_INDEX_DATA:2, //下载大盘的K线数据
+ JOB_DOWNLOAD_SYMBOL_LATEST_DATA:3, //最新的股票行情数据
+ JOB_DOWNLOAD_INDEX_INCREASE_DATA: 4, //涨跌股票个数统计数据
+ JOB_DOWNLOAD_VOLR_DATA: 5, //5日量比均量下载量比数据
+
+ JOB_DOWNLOAD_FINVALUE:301, //引用专业财务数据 FINVALUE(ID),ID为数据编号
+ JOB_DOWNLOAD_FINONE:302, //引用指定年和月日的某类型的财务数据 FINONE(ID,Y,MMDD),ID为数据编号,Y和MMDD表示年和月日.
+ JOB_DOWNLOAD_FINANCE:303, //FINANCE(ID) 基础财务数据
+ JOB_DOWNLOAD_GPJYVALUE:304, //引用股票交易类数据 GPJYVALUE(ID,N,TYPE),ID为数据编号,N表示第几个数据,TYPE:为1表示做平滑处理,没有数据的周期返回上一周期的值;为0表示不做平滑处理
+ JOB_DOWNLOAD_VARIANT:305, //CAPITAL , TOTALCAPITAL, EXCHANGE
+
+ JOB_CUSTOM_FUNCTION_DATA:6000, //自定义函数
+ JOB_CUSTOM_VARIANT_DATA:6001, //自定义变量
+
+ JOB_DOWNLOAD_MARGIN_BALANCE: 1000, //融资融券余额
+ JOB_DOWNLOAD_MARGIN_RATE: 1001, //融资占比
+
+ JOB_DOWNLOAD_MARGIN_BUY_BALANCE: 1010, //买入信息-融资余额
+ JOB_DOWNLOAD_MARGIN_BUY_AMOUNT: 1011, //买入信息-买入额
+ JOB_DOWNLOAD_MARGIN_BUY_REPAY: 1012, //买入信息-偿还额
+ JOB_DOWNLOAD_MARGIN_BUY_NET: 1013, //买入信息-融资净买入
+
+ JOB_DOWNLOAD_MARGIN_SELL_BALANCE: 1020, //卖出信息-融券余量
+ JOB_DOWNLOAD_MARGIN_SELL_VOLUME: 1021, //卖出信息-卖出量
+ JOB_DOWNLOAD_MARGIN_SELL_REPAY: 1022, //卖出信息-偿还量
+ JOB_DOWNLOAD_MARGIN_SELL_NET: 1023, //卖出信息-融券净卖出
+
+ JOB_DOWNLOAD_NEWS_ANALYSIS_NEGATIVE: 2000, //负面新闻统计
+ JOB_DOWNLOAD_NEWS_ANALYSIS_RESEARCH: 2001, //机构调研
+ JOB_DOWNLOAD_NEWS_ANALYSIS_INTERACT: 2002, //互动易
+ JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE: 2003, //股东增持
+ JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE2: 2004, //股东减持
+ JOB_DOWNLOAD_NEWS_ANALYSIS_TRUSTHOLDER: 2005, //信托持股
+ JOB_DOWNLOAD_NEWS_ANALYSIS_BLOCKTRADING: 2006, //大宗交易
+ JOB_DOWNLOAD_NEWS_ANALYSIS_COMPANYNEWS: 2007, //官网新闻
+ JOB_DOWNLOAD_NEWS_ANALYSIS_TOPMANAGERS: 2008, //高管要闻
+ JOB_DOWNLOAD_NEWS_ANALYSIS_PLEDGE: 2009, //股权质押
+
+ JOB_CUSTOM_FUNCTION_DATA: 6000, //自定义函数
+ JOB_CUSTOM_VARIANT_DATA: 6001, //自定义变量
+
+ JOB_DOWNLOAD_CUSTOM_API_DATA: 30000, //自定义数据
+
+ JOB_RUN_SCRIPT:10000, //执行脚本
+
+ //融资融券
+ GetMarginJobID: function (value)
+ {
+ let dataMap = new Map([
+ [1, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BALANCE], //MARGIN(1) 融资融券余额
+ [2, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_RATE], //MARGIN(2) 融资占比
+
+ [3, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_BALANCE], //MARGIN(3) 买入信息-融资余额
+ [4, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_AMOUNT], //MARGIN(4) 买入信息-买入额
+ [5, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_REPAY], //MARGIN(5) 买入信息-偿还额
+ [6, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_NET], //MARGIN(6) 买入信息-融资净买入
+
+ [7, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_BALANCE], //MARGIN(7) 卖出信息-融券余量
+ [8, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_VOLUME], //MARGIN(8) 卖出信息-卖出量
+ [9, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_REPAY], //MARGIN(9) 卖出信息-偿还量
+ [10, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_NET], //MARGIN(10) 卖出信息-融券净卖出
+ ]);
+
+ if (dataMap.has(value)) return dataMap.get(value);
+
+ return null;
+ },
+
+ GetNewsAnalysisID: function (value)
+ {
+ let dataMap = new Map([
+ [1, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_NEGATIVE], //NEWS(1) 负面新闻统计
+ [2, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_RESEARCH], //NEWS(2) 机构调研统计
+ [3, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_INTERACT], //NEWS(3) 互动易
+ [4, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE], //NEWS(4) 股东增持
+ [5, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE2], //NEWS(5) 股东减持
+ [6, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_TRUSTHOLDER], //NEWS(6) 信托持股
+ [7, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_BLOCKTRADING], //NEWS(7) 大宗交易
+ [8, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_COMPANYNEWS], //NEWS(8) 官网新闻
+ [9, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_TOPMANAGERS], //NEWS(9) 高管要闻
+ [10, JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_PLEDGE], //NEWS(10) 股权质押
+ ]);
+
+ if (dataMap.has(value)) return dataMap.get(value);
+
+ return null;
+ }
+
+};
+
+function JSExecute(ast,option)
+{
+ this.AST=ast; //语法树
+
+ this.ErrorHandler=new ErrorHandler();
+ this.VarTable=new Map(); //变量表
+ this.OutVarTable=new Array(); //输出变量
+ this.Arguments=[];
+
+ //脚本自动变量表, 只读
+ this.ConstVarTable=new Map([
+ //个股数据
+ ['CLOSE', null], ['VOL', null], ['OPEN', null], ['HIGH', null], ['LOW', null], ['AMOUNT', null], ['AMO', null], ['VOLINSTK',null],
+ ['C', null], ['V', null], ['O', null], ['H', null], ['L', null], ['VOLR', null],
+
+ //日期类
+ ['DATE', null], ['YEAR', null], ['MONTH', null], ['PERIOD', null], ['WEEK', null],["TIME",null],
+
+ //大盘数据
+ ['INDEXA',null],['INDEXC',null],['INDEXH',null],['INDEXL',null],['INDEXO',null],['INDEXV',null],
+ ['INDEXADV', null], ['INDEXDEC', null],
+
+ ['CURRBARSCOUNT', null], //到最后交易日的周期数
+ ['ISLASTBAR', null], //判断是否为最后一个周期
+
+ ["TOTALCAPITAL",null], //总股本
+ ['CAPITAL', null], //流通股本(手)
+ ['EXCHANGE', null], //换手率
+ ['SETCODE', null], //市场类型
+ ['CODE', null], //品种代码
+ ['STKNAME', null], //品种名称
+
+ ['HYBLOCK', null], //所属行业板块
+ ['DYBLOCK', null], //所属地域板块
+ ['GNBLOCK', null], //所属概念
+ ["FGBLOCK",null], //所属风格板块
+ ["ZSBLOCK",null], //所属指数板块
+ ["ZHBLOCK",null], //所属组合板块
+ ["ZDBLOCK",null], //所属自定义板块
+ ["HYZSCODE",null],
+
+ ["GNBLOCKNUM",null], //所属概念板块的个数
+ ["FGBLOCKNUM",null], //所属风格板块的个数
+ ["ZSBLOCKNUM",null], //所属指数板块的个数
+ ["ZHBLOCKNUM",null], //所属组合板块的个数
+ ["ZDBLOCKNUM",null], //所属自定义板块的个数
+
+ ["HYSYL",null], //指数市盈率或个股所属行业的市盈率
+ ["HYSJL",null], //指数市净率或个股所属行业的市净率
+
+ ['DRAWNULL', null]
+ ]);
+
+ this.SymbolData=new JSSymbolData(this.AST,option,this);
+ this.Algorithm = new JSAlgorithm(this.ErrorHandler, this.SymbolData);
+ this.Draw = new JSDraw(this.ErrorHandler, this.SymbolData);
+ this.JobList=[]; //执行的任务队列
+
+ this.UpdateUICallback=null; //回调
+ this.CallbackParam=null;
+
+ if (option)
+ {
+ if (option.Callback) this.UpdateUICallback=option.Callback;
+ if (option.CallbackParam) this.CallbackParam=option.CallbackParam;
+ if (option.Arguments) this.Arguments=option.Arguments;
+ }
+
+ this.Execute=function()
+ {
+ JSConsole.Complier.Log('[JSExecute::Execute] JobList', this.JobList);
+ this.RunNextJob();
+ }
+
+ this.RunNextJob=function()
+ {
+ if (this.JobList.length<=0) return;
+
+ var jobItem=this.JobList.shift();
+
+ switch (jobItem.ID)
+ {
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SYMBOL_DATA:
+ return this.SymbolData.GetSymbolData();
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_INDEX_DATA:
+ return this.SymbolData.GetIndexData();
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_INDEX_INCREASE_DATA:
+ return this.SymbolData.GetIndexIncreaseData(jobItem);
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SYMBOL_LATEST_DATA:
+ return this.SymbolData.GetLatestData();
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_VOLR_DATA: //量比
+ return this.SymbolData.GetVolRateData(jobItem);
+
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_FINONE:
+ return this.SymbolData.GetFinOne(jobItem);
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_FINVALUE:
+ return this.SymbolData.GetFinValue(jobItem);
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_FINANCE:
+ return this.SymbolData.GetFinance(jobItem);
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_GPJYVALUE:
+ return this.SymbolData.GetGPJYValue(jobItem);
+
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_VARIANT: //CAPITAL, TOTALCAPITAL
+ return this.SymbolData.GetVariantData(jobItem);
+
+ case JS_EXECUTE_JOB_ID.JOB_CUSTOM_VARIANT_DATA:
+ return this.SymbolData.GetCustomVariantData(jobItem);
+
+ case JS_EXECUTE_JOB_ID.JOB_CUSTOM_FUNCTION_DATA:
+ return this.SymbolData.GetCustomFunctionData(jobItem);
+
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BALANCE:
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_RATE:
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_BALANCE: //买入信息-融资余额
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_AMOUNT: //买入信息-买入额
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_REPAY: //买入信息-偿还额
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_NET: //买入信息-融资净买入
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_BALANCE: //卖出信息-融券余量
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_VOLUME: //卖出信息-卖出量
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_REPAY: //卖出信息-偿还量
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_NET: //卖出信息-融券净卖出
+ return this.SymbolData.GetMarginData(jobItem.ID);
+
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_NEGATIVE: //负面新闻
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_RESEARCH: //机构调研
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_INTERACT: //互动易
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE: //股东增持
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE2: //股东减持
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_TRUSTHOLDER: //信托持股
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_BLOCKTRADING: //大宗交易
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_COMPANYNEWS: //官网新闻
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_TOPMANAGERS: //高管要闻
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_PLEDGE: //股权质押
+ return this.SymbolData.GetNewsAnalysisData(jobItem.ID);
+
+ case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_CUSTOM_API_DATA:
+ return this.SymbolData.DownloadCustomAPIData(jobItem);
+
+ case JS_EXECUTE_JOB_ID.JOB_RUN_SCRIPT:
+ return this.Run();
+ }
+ }
+
+ this.ReadSymbolData=function(name,node)
+ {
+ switch(name)
+ {
+ case 'CLOSE':
+ case 'C':
+ case 'VOL':
+ case 'V':
+ case 'OPEN':
+ case 'O':
+ case 'HIGH':
+ case 'H':
+ case 'LOW':
+ case 'L':
+ case 'AMOUNT':
+ case 'VOLINSTK':
+ return this.SymbolData.GetSymbolCacheData(name);
+ case 'VOLR':
+ return this.SymbolData.GetVolRateCacheData(node);
+
+ //大盘数据
+ case 'INDEXA':
+ case 'INDEXC':
+ case 'INDEXH':
+ case 'INDEXO':
+ case 'INDEXV':
+ case 'INDEXL':
+ case 'INDEXADV':
+ case 'INDEXDEC':
+ return this.SymbolData.GetIndexCacheData(name);
+
+ case 'CURRBARSCOUNT':
+ return this.SymbolData.GetCurrBarsCount();
+ case 'ISLASTBAR':
+ return this.SymbolData.GetIsLastBar();
+ case "TOTALCAPITAL":
+ case 'CAPITAL':
+ case 'EXCHANGE':
+
+ case "HYBLOCK":
+ case "DYBLOCK":
+ case "GNBLOCK":
+ case "FGBLOCK":
+ case "ZSBLOCK":
+ case "ZHBLOCK":
+ case "ZDBLOCK":
+ case "HYZSCODE":
+
+ case "GNBLOCKNUM":
+ case "FGBLOCKNUM":
+ case "ZSBLOCKNUM":
+ case "ZHBLOCKNUM":
+ case "ZDBLOCKNUM":
+
+ case "HYSYL":
+ case "HYSJL":
+ return this.SymbolData.GetStockCacheData({ VariantName:name, Node:node });
+ case 'SETCODE':
+ return this.SymbolData.SETCODE();
+
+ case 'CODE':
+ return this.SymbolData.GetSymbol();
+ case 'STKNAME':
+ return this.SymbolData.GetName();
+
+ case 'TIME':
+ return this.SymbolData.TIME();
+ case 'DATE':
+ return this.SymbolData.DATE();
+ case 'YEAR':
+ return this.SymbolData.YEAR();
+ case 'MONTH':
+ return this.SymbolData.MONTH();
+ case 'WEEK':
+ return this.SymbolData.WEEK();
+ case 'PERIOD':
+ return this.SymbolData.PERIOD();
+
+ case 'DRAWNULL':
+ return this.SymbolData.GetDrawNull();
+ }
+ }
+
+ this.ReadCustomVariant=function(name,node)
+ {
+ return this.SymbolData.GetStockCacheData({ VariantName:name, Node:node });
+ }
+
+ //读取变量
+ this.ReadVariable=function(name,node)
+ {
+ if (this.ConstVarTable.has(name))
+ {
+ let data=this.ConstVarTable.get(name);
+
+ if (data==null) //动态加载,用到再加载
+ {
+ data=this.ReadSymbolData(name,node);
+ this.ConstVarTable.set(name,data);
+ }
+
+ return data;
+ }
+
+ if (g_JSComplierResource.IsCustomVariant(name)) return this.ReadCustomVariant(name,node); //读取自定义变量
+
+ if (this.VarTable.has(name)) return this.VarTable.get(name);
+
+ this.ThrowUnexpectedNode(node, '变量'+name+'不存在');
+ return null;
+ }
+
+ this.ReadMemberVariable = function (node)
+ {
+ var obj = node.Object;
+ var member = node.Property;
+
+ let maiObj;
+ if (obj.Type == Syntax.BinaryExpression || obj.Type == Syntax.LogicalExpression)
+ maiObj = this.VisitBinaryExpression(obj);
+ else if (obj.Type == Syntax.CallExpression)
+ maiObj = this.VisitCallExpression(obj);
+ else
+ maiObj = this.GetNodeValue(obj);
+
+ if (!maiObj) return null;
+ var value = maiObj[member.Name];
+ if (value) return value;
+
+ return null;
+ }
+
+ //单数据转成数组 个数和历史数据一致
+ this.SingleDataToArrayData = function (value)
+ {
+ let count = this.SymbolData.Data.Data.length;
+ let result = [];
+ for (let i = 0; i < count; ++i)
+ {
+ result[i] = value;
+ }
+
+ return result;
+ }
+
+ this.RunAST=function()
+ {
+ //预定义的变量
+ for(let i in this.Arguments)
+ {
+ let item =this.Arguments[i];
+ this.VarTable.set(item.Name,item.Value);
+ }
+
+ if (!this.AST) this.ThrowError();
+ if (!this.AST.Body) this.ThrowError();
+
+ for(let i in this.AST.Body)
+ {
+ let item =this.AST.Body[i];
+ this.VisitNode(item);
+
+ //输出变量
+ if (item.Type==Syntax.ExpressionStatement && item.Expression)
+ {
+ if (item.Expression.Type==Syntax.AssignmentExpression && item.Expression.Operator==':' && item.Expression.Left)
+ {
+ let assignmentItem=item.Expression;
+ let varName=assignmentItem.Left.Name;
+ let outVar=this.VarTable.get(varName);
+ var type=0;
+ if (!Array.isArray(outVar))
+ {
+ if (typeof (outVar) == 'string')
+ {
+ var floatValue=parseFloat(outVar);
+ if (IFrameSplitOperator.IsNumber(floatValue))
+ {
+ outVar=this.SingleDataToArrayData(floatValue);
+ }
+ else
+ {
+ outVar=this.SingleDataToArrayData(outVar);
+ type=1001;
+ }
+ }
+ else outVar = this.SingleDataToArrayData(outVar);
+ }
+
+ this.OutVarTable.push({Name:varName, Data:outVar,Type:type});
+ }
+ else if (item.Expression.Type==Syntax.CallExpression)
+ {
+ let callItem=item.Expression;
+ if (this.Draw.IsDrawFunction(callItem.Callee.Name))
+ {
+ let draw=callItem.Draw;
+ draw.Name=callItem.Callee.Name;
+ this.OutVarTable.push({Name:draw.Name, Draw:draw, Type:1});
+ }
+ else
+ {
+ let outVar=callItem.Out;
+ varName=`__temp_c_${callItem.Callee.Name}_${i}__`;
+ var type=0;
+ if (!Array.isArray(outVar)) outVar=this.SingleDataToArrayData(outVar);
+ this.OutVarTable.push({Name:varName, Data:outVar,Type:type,NoneName:true});
+ }
+ }
+ else if (item.Expression.Type==Syntax.Identifier)
+ {
+ let varName=item.Expression.Name;
+ let outVar=this.ReadVariable(varName,item.Expression);
+ var type=0;
+ if (!Array.isArray(outVar))
+ {
+ if (typeof(outVar)=='string') outVar=this.SingleDataToArrayData(parseFloat(outVar));
+ else outVar=this.SingleDataToArrayData(outVar);
+ }
+
+ varName="__temp_i_"+i+"__";
+ this.OutVarTable.push({Name:varName, Data:outVar, Type:type, NoneName:true});
+ }
+ else if (item.Expression.Type==Syntax.BinaryExpression)
+ {
+ var varName="__temp_b_"+i+"__";
+ let outVar=item.Expression.Out;
+ var type=0;
+ if (!Array.isArray(outVar)) outVar=this.SingleDataToArrayData(outVar);
+ this.OutVarTable.push({Name:varName, Data:outVar,Type:type, NoneName:true});
+ }
+ else if (item.Expression.Type==Syntax.LogicalExpression) //逻辑语句 如 T1 AND T2
+ {
+ var varName="__temp_l_"+i+"__";
+ let outVar=item.Expression.Out;
+ var type=0;
+ if (!Array.isArray(outVar)) outVar=this.SingleDataToArrayData(outVar);
+ this.OutVarTable.push({Name:varName, Data:outVar,Type:type, NoneName:true});
+ }
+ else if (item.Expression.Type==Syntax.SequenceExpression)
+ {
+ let varName;
+ let draw;
+ let color;
+ let lineWidth;
+ let colorStick=false;
+ let pointDot=false;
+ let circleDot=false;
+ let lineStick=false;
+ let stick=false;
+ let volStick=false;
+ let isShow = true;
+ let isExData = false;
+ let isDotLine = false;
+ let isOverlayLine = false; //叠加线
+ let isNoneName=false;
+ var isShowTitle=true;
+ //显示在位置之上,对于DRAWTEXT和DRAWNUMBER等函数有用,放在语句的最后面(不能与LINETHICK等函数共用),比如:
+ //DRAWNUMBER(CLOSE>OPEN,HIGH,CLOSE),DRAWABOVE;
+ var isDrawAbove=false;
+ for(let j in item.Expression.Expression)
+ {
+ let itemExpression=item.Expression.Expression[j];
+ if (itemExpression.Type==Syntax.AssignmentExpression && itemExpression.Operator==':' && itemExpression.Left)
+ {
+ varName = itemExpression.Left.Name;
+ let varValue = this.VarTable.get(varName);
+ if (!Array.isArray(varValue))
+ {
+ varValue = this.SingleDataToArrayData(varValue);
+ this.VarTable.set(varName, varValue); //把常量放到变量表里
+ }
+ }
+ else if (itemExpression.Type==Syntax.Identifier)
+ {
+ let value=itemExpression.Name;
+ if (value==='COLORSTICK') colorStick=true;
+ else if (value==='POINTDOT') pointDot=true;
+ else if (value==='CIRCLEDOT') circleDot=true;
+ else if (value == 'DOTLINE') isDotLine = true;
+ else if (value==='LINESTICK') lineStick=true;
+ else if (value==='STICK') stick=true;
+ else if (value==='VOLSTICK') volStick=true;
+ else if (value==="DRAWABOVE") isDrawAbove=true;
+ else if (value.indexOf('COLOR')==0) color=value;
+ else if (value.indexOf('LINETHICK')==0) lineWidth=value;
+ else if (value.indexOf('NODRAW') == 0) isShow = false;
+ else if (value.indexOf('EXDATA') == 0) isExData = true; //扩展数据, 不显示再图形里面
+ else if (value.indexOf('LINEOVERLAY') == 0) isOverlayLine = true;
+ else if (value.indexOf("NOTEXT")==0 || value.indexOf("NOTITLE")==0) isShowTitle=false; //标题不显示
+ else
+ {
+ varName=itemExpression.Name;
+ let varValue=this.ReadVariable(varName,itemExpression);
+ if (!Array.isArray(varValue)) varValue=this.SingleDataToArrayData(varValue);
+ varName="__temp_si_"+i+"__";
+ isNoneName=true;
+ this.VarTable.set(varName,varValue); //放到变量表里
+ }
+ }
+ else if (itemExpression.Type == Syntax.Literal) //常量
+ {
+ let aryValue = this.SingleDataToArrayData(itemExpression.Value);
+ varName = itemExpression.Value.toString();
+ this.VarTable.set(varName, aryValue); //把常量放到变量表里
+ }
+ else if (itemExpression.Type==Syntax.CallExpression)
+ {
+ if (this.Draw.IsDrawFunction(itemExpression.Callee.Name))
+ {
+ draw=itemExpression.Draw;
+ draw.Name=itemExpression.Callee.Name;
+ }
+ else
+ {
+ let varValue=itemExpression.Out;
+ varName=`__temp_sc_${itemExpression.Callee.Name}_${i}__`;
+ isNoneName=true;
+ this.VarTable.set(varName,varValue);
+ }
+ }
+ else if (itemExpression.Type==Syntax.BinaryExpression)
+ {
+ varName="__temp_sb_"+i+"__";
+ let aryValue=itemExpression.Out;
+ isNoneName=true;
+ this.VarTable.set(varName,aryValue);
+ }
+ }
+
+ if (pointDot && varName) //圆点
+ {
+ let outVar=this.VarTable.get(varName);
+ let value={Name:varName, Data:outVar, Radius:g_JSChartResource.POINTDOT.Radius, Type:3};
+ if (color) value.Color=color;
+ if (lineWidth) value.LineWidth = lineWidth;
+ this.OutVarTable.push(value);
+ }
+ else if (circleDot && varName) //圆点
+ {
+ let outVar=this.VarTable.get(varName);
+ let value={Name:varName, Data:outVar, Radius:g_JSChartResource.CIRCLEDOT.Radius, Type:3};
+ if (color) value.Color=color;
+ if (lineWidth) value.LineWidth = lineWidth;
+ this.OutVarTable.push(value);
+ }
+ else if (lineStick && varName) //LINESTICK 同时画出柱状线和指标线
+ {
+ let outVar=this.VarTable.get(varName);
+ let value={Name:varName, Data:outVar, Type:4};
+ if (color) value.Color=color;
+ if (lineWidth) value.LineWidth=lineWidth;
+ this.OutVarTable.push(value);
+ }
+ else if (stick && varName) //STICK 画柱状线
+ {
+ let outVar=this.VarTable.get(varName);
+ let value={Name:varName, Data:outVar, Type:5};
+ if (color) value.Color=color;
+ if (lineWidth) value.LineWidth=lineWidth;
+ this.OutVarTable.push(value);
+ }
+ else if (volStick && varName) //VOLSTICK 画彩色柱状线
+ {
+ let outVar=this.VarTable.get(varName);
+ let value={Name:varName, Data:outVar, Type:6};
+ if (color) value.Color=color;
+ this.OutVarTable.push(value);
+ }
+ else if (colorStick && varName) //CYW: SUM(VAR4,10)/10000, COLORSTICK; 画上下柱子
+ {
+ let outVar=this.VarTable.get(varName);
+ let value={Name:varName, Data:outVar, Color:color, Type:2};
+ if (lineWidth) value.LineWidth=lineWidth;
+ if (color) value.Color=color;
+ this.OutVarTable.push(value);
+ }
+ else if (varName && color)
+ {
+ let outVar=this.VarTable.get(varName);
+ let value={Name:varName, Data:outVar, Color:color, Type:0};
+ if (lineWidth) value.LineWidth=lineWidth;
+ if (isShow == false) value.IsShow = false;
+ if (isExData == true) value.IsExData = true;
+ if (isDotLine == true) value.IsDotLine = true;
+ if (isOverlayLine == true) value.IsOverlayLine = true;
+ if (isNoneName==true) value.NoneName=true;
+ if (isShowTitle==false) value.IsShowTitle=false;
+ this.OutVarTable.push(value);
+ }
+ else if (draw)
+ {
+ var outVar = { Name: draw.Name, Draw: draw, Type: 1 };
+ if (color) outVar.Color = color;
+ if (lineWidth) outVar.LineWidth = lineWidth;
+ if (isDrawAbove) outVar.IsDrawAbove=true;
+ this.OutVarTable.push(outVar);
+ }
+ else if (varName)
+ {
+ let outVar = this.VarTable.get(varName);
+ let value = { Name: varName, Data: outVar, Type: 0 };
+ if (color) value.Color = color;
+ if (lineWidth) value.LineWidth = lineWidth;
+ if (isShow == false) value.IsShow = false;
+ if (isExData == true) value.IsExData = true;
+ if (isDotLine == true) value.IsDotLine = true;
+ if (isOverlayLine == true) value.IsOverlayLine = true;
+ if (isShowTitle==false) value.IsShowTitle=false;
+ this.OutVarTable.push(value);
+ }
+ }
+ }
+ }
+
+ JSConsole.Complier.Log('[JSExecute::Run]', this.VarTable);
+
+ return this.OutVarTable;
+ }
+
+ this.Run=function()
+ {
+ let data=this.RunAST();//执行脚本
+ JSConsole.Complier.Log('[JSComplier.Run] execute finish', data);
+
+ if (this.UpdateUICallback)
+ {
+ JSConsole.Complier.Log('[JSComplier.Run] invoke UpdateUICallback.');
+ this.UpdateUICallback(data,this.CallbackParam);
+ }
+ }
+
+ this.VisitNode=function(node)
+ {
+ switch(node.Type)
+ {
+ case Syntax.SequenceExpression:
+ this.VisitSequenceExpression(node);
+ break;
+ case Syntax.ExpressionStatement:
+ this.VisitNode(node.Expression);
+ break;
+ case Syntax.AssignmentExpression:
+ this.VisitAssignmentExpression(node);
+ break;
+ case Syntax.BinaryExpression:
+ case Syntax.LogicalExpression:
+ this.VisitBinaryExpression(node);
+ break;
+ case Syntax.CallExpression:
+ this.VisitCallExpression(node);
+ break;
+ }
+ }
+
+ this.VisitSequenceExpression=function(node)
+ {
+ for(let i in node.Expression)
+ {
+ let item =node.Expression[i];
+ this.VisitNode(item);
+ }
+ }
+
+ //函数调用
+ this.VisitCallExpression=function(node)
+ {
+ let funcName=node.Callee.Name;
+ let args=[];
+ for(let i in node.Arguments)
+ {
+ let item=node.Arguments[i];
+ let value;
+ if (item.Type==Syntax.BinaryExpression || item.Type==Syntax.LogicalExpression)
+ value=this.VisitBinaryExpression(item);
+ else if (item.Type==Syntax.CallExpression)
+ value=this.VisitCallExpression(item);
+ else
+ value=this.GetNodeValue(item);
+ args.push(value);
+ }
+
+ //if (JS_EXECUTE_DEBUG_LOG) JSConsole.Complier.Log('[JSExecute::VisitCallExpression]' , funcName, '(', args.toString() ,')');
+ if (g_JSComplierResource.IsCustomFunction(funcName)) //自定义函数
+ {
+ var data=this.Algorithm.CallCustomFunction(funcName, args, this.SymbolData, node);
+ node.Out=[];
+ node.Draw=null;
+
+ if (data)
+ {
+ if (data.Out) node.Out=data.Out;
+ if (data.Draw) node.Draw=data.Draw;
+ }
+
+ return node.Out;
+ }
+
+ switch(funcName)
+ {
+ case 'DYNAINFO': //行情最新数据
+ node.Out=this.SymbolData.GetLatestCacheData(args[0]);
+ break;
+ case 'STICKLINE':
+ node.Draw=this.Draw.STICKLINE(args[0],args[1],args[2],args[3],args[4]);
+ node.Out=[];
+ break;
+ case 'DRAWTEXT':
+ node.Draw=this.Draw.DRAWTEXT(args[0],args[1],args[2]);
+ node.Out=[];
+ break;
+ case 'SUPERDRAWTEXT':
+ node.Draw = this.Draw.SUPERDRAWTEXT(args[0], args[1], args[2], args[3], args[4]);
+ node.Out = [];
+ break;
+ case 'DRAWTEXT_FIX':
+ node.Draw=this.Draw.DRAWTEXT_FIX(args[0],args[1],args[2],args[3],args[4]);
+ node.Out=[];
+ break;
+ case 'DRAWICON':
+ node.Draw = this.Draw.DRAWICON(args[0], args[1], args[2]);
+ node.Out = [];
+ break;
+ case 'DRAWLINE':
+ node.Draw=this.Draw.DRAWLINE(args[0],args[1],args[2],args[3],args[4]);
+ node.Out=node.Draw.DrawData;
+ break;
+ case 'DRAWBAND':
+ node.Draw=this.Draw.DRAWBAND(args[0],args[1],args[2],args[3]);
+ node.Out=[];
+ break;
+ case 'DRAWKLINE':
+ node.Draw = this.Draw.DRAWKLINE(args[0], args[1], args[2], args[3]);
+ node.Out = [];
+ break;
+ case 'DRAWKLINE_IF':
+ node.Draw = this.Draw.DRAWKLINE_IF(args[0], args[1], args[2], args[3], args[4]);
+ node.Out = [];
+ break;
+ case 'PLOYLINE':
+ case 'POLYLINE':
+ node.Draw = this.Draw.POLYLINE(args[0], args[1]);
+ node.Out = node.Draw.DrawData;
+ break;
+ case 'DRAWNUMBER':
+ node.Draw = this.Draw.DRAWNUMBER(args[0], args[1], args[2]);
+ node.Out = node.Draw.DrawData.Value;
+ break;
+ case 'RGB':
+ node.Out = this.Draw.RGB(args[0], args[1], args[2]);
+ break;
+ case 'RGBA':
+ node.Out = this.Draw.RGBA(args[0], args[1], args[2],args[3]);
+ break;
+ case 'DRAWRECTREL':
+ node.Draw = this.Draw.DRAWRECTREL(args[0], args[1], args[2], args[3], args[4]);
+ node.Out = [];
+ break;
+ case 'DRAWGBK':
+ node.Draw=this.Draw.DRAWGBK(args[0],args[1],args[2],args[3]);
+ node.Out=[];
+ break;
+ case 'DRAWGBK2':
+ node.Draw=this.Draw.DRAWGBK2(args[0],args[1],args[2],args[3]);
+ node.Out=[];
+ break;
+ case 'CODELIKE':
+ node.Out=this.SymbolData.CODELIKE(args[0]);
+ break;
+ case 'NAMELIKE':
+ node.Out = this.SymbolData.NAMELIKE(args[1]);
+ break;
+ case 'REFDATE':
+ node.Out = this.SymbolData.REFDATE(args[0], args[1]);
+ break;
+ case 'FINANCE':
+ node.Out=this.SymbolData.GetStockCacheData( {FunctionName:funcName, Args:args, ArgCount:1, Node:node } );
+ break;
+ case "FINVALUE":
+ node.Out=this.SymbolData.GetStockCacheData( {FunctionName:funcName, Args:args, ArgCount:1, Node:node } );
+ break;
+ case "FINONE":
+ node.Out=this.SymbolData.GetStockCacheData( {FunctionName:funcName, Args:args, ArgCount:3, Node:node } );
+ break;
+ case "GPJYVALUE":
+ node.Out=this.SymbolData.GetStockCacheData( {FunctionName:funcName, Args:args, ArgCount:3, Node:node } );
+ break;
+ case "MARGIN":
+ node.Out = this.SymbolData.GetMarginCacheData(args[0], node);
+ break;
+ case "NEWS":
+ node.Out = this.SymbolData.GetNewsAnalysisCacheData(args[0], node);
+ break;
+ case 'UPCOUNT':
+ case 'DOWNCOUNT':
+ node.Out = this.SymbolData.GetIndexIncreaseCacheData(funcName, args[0], node);
+ break;
+ case 'LOADAPIDATA':
+ node.Out = this.SymbolData.GetCustomApiData(args);
+ break;
+ case "INBLOCK":
+ node.Out=this.SymbolData.IsInBlock(args[0],node);
+ break;
+ default:
+ node.Out=this.Algorithm.CallFunction(funcName, args,node);
+ break;
+ }
+
+ return node.Out;
+ }
+
+ //赋值
+ this.VisitAssignmentExpression=function(node)
+ {
+ let left=node.Left;
+ if (left.Type!=Syntax.Identifier) this.ThrowUnexpectedNode(node);
+
+ let varName=left.Name;
+
+ let right=node.Right;
+ let value=null;
+ if (right.Type==Syntax.BinaryExpression || right.Type==Syntax.LogicalExpression)
+ value=this.VisitBinaryExpression(right);
+ else if (right.Type==Syntax.CallExpression)
+ value=this.VisitCallExpression(right);
+ else if (right.Type==Syntax.Literal)
+ value=right.Value;
+ else if (right.Type==Syntax.Identifier) //右值是变量
+ value=this.ReadVariable(right.Name,right);
+ else if (right.Type == Syntax.MemberExpression)
+ value = this.ReadMemberVariable(right);
+
+ if (JS_EXECUTE_DEBUG_LOG) JSConsole.Complier.Log('[JSExecute::VisitAssignmentExpression]' , varName, ' = ',value);
+ this.VarTable.set(varName,value);
+ }
+
+ //逻辑运算
+ this.VisitBinaryExpression=function(node)
+ {
+ let stack=[];
+ stack.push(node);
+ let temp=null;
+
+ while(stack.length!=0)
+ {
+ temp=stack[stack.length-1];
+ if (temp.Left && node!=temp.Left && node!=temp.Right)
+ {
+ stack.push(temp.Left);
+ }
+ else if (temp.Right && node!=temp.Right)
+ {
+ stack.push(temp.Right);
+ }
+ else
+ {
+ let value=stack.pop();
+ if (value.Type==Syntax.BinaryExpression) //只遍历操作符就可以
+ {
+ let leftValue=this.GetNodeValue(value.Left);
+ let rightValue=this.GetNodeValue(value.Right);
+
+ if (JS_EXECUTE_DEBUG_LOG) JSConsole.Complier.Log('[JSExecute::VisitBinaryExpression] BinaryExpression',value , leftValue, rightValue);
+ value.Out=null; //保存中间值
+
+ switch(value.Operator)
+ {
+ case '-':
+ value.Out=this.Algorithm.Subtract(leftValue,rightValue);
+ break;
+ case '*':
+ value.Out=this.Algorithm.Multiply(leftValue,rightValue);
+ break;
+ case '/':
+ value.Out=this.Algorithm.Divide(leftValue,rightValue)
+ break;
+ case '+':
+ value.Out=this.Algorithm.Add(leftValue,rightValue);
+ break;
+ case '>':
+ value.Out=this.Algorithm.GT(leftValue,rightValue);
+ break;
+ case '>=':
+ value.Out=this.Algorithm.GTE(leftValue,rightValue);
+ break;
+ case '<':
+ value.Out=this.Algorithm.LT(leftValue,rightValue);
+ break;
+ case '<=':
+ value.Out=this.Algorithm.LTE(leftValue,rightValue);
+ break;
+ case '==':
+ case '=':
+ value.Out=this.Algorithm.EQ(leftValue,rightValue);
+ break;
+ case '!=':
+ case '<>':
+ value.Out = this.Algorithm.NEQ(leftValue, rightValue);
+ break;
+ }
+
+ if (JS_EXECUTE_DEBUG_LOG) JSConsole.Complier.Log('[JSExecute::VisitBinaryExpression] BinaryExpression',value);
+ }
+ else if (value.Type==Syntax.LogicalExpression)
+ {
+ let leftValue=this.GetNodeValue(value.Left);
+ let rightValue=this.GetNodeValue(value.Right);
+
+ if (JS_EXECUTE_DEBUG_LOG) JSConsole.Complier.Log('[JSExecute::VisitBinaryExpression] LogicalExpression',value , leftValue, rightValue);
+ value.Out=null; //保存中间值
+
+ switch(value.Operator)
+ {
+ case '&&':
+ case 'AND':
+ value.Out=this.Algorithm.And(leftValue,rightValue);
+ break;
+ case '||':
+ case 'OR':
+ value.Out=this.Algorithm.Or(leftValue,rightValue);
+ break;
+ }
+
+ if (JS_EXECUTE_DEBUG_LOG) JSConsole.Complier.Log('[JSExecute::VisitBinaryExpression] LogicalExpression',value);
+ }
+
+ node=temp;
+ }
+ }
+
+ return node.Out;
+
+ }
+
+ this.GetNodeValue=function(node)
+ {
+ switch(node.Type)
+ {
+ case Syntax.Literal: //数字
+ return node.Value;
+ case Syntax.UnaryExpression:
+ if (node.Operator=='-')
+ {
+ let value=this.GetNodeValue(node.Argument);
+ return this.Algorithm.Subtract(0,value);
+ }
+ return node.Argument.Value;
+ case Syntax.Identifier:
+ let value=this.ReadVariable(node.Name,node);
+ return value;
+ case Syntax.BinaryExpression:
+ case Syntax.LogicalExpression:
+ return node.Out;
+ case Syntax.CallExpression:
+ return this.VisitCallExpression(node);
+ default:
+ this.ThrowUnexpectedNode(node);
+ }
+ }
+
+ this.ThrowUnexpectedNode=function(node,message)
+ {
+ let marker=node.Marker;
+ let msg=message || "执行异常";
+
+ return this.ErrorHandler.ThrowError(marker.Index,marker.Line,marker.Column,msg);
+
+ }
+
+ this.ThrowError=function()
+ {
+
+ }
+}
+
+//对外导出类
+function JSComplier()
+{
+
+}
+
+
+//词法分析
+JSComplier.Tokenize=function(code)
+{
+ JSConsole.Complier.Log('[JSComplier.Tokenize]', code);
+ let tokenizer=new Tokenizer(code);
+ let tokens=[];
+ try
+ {
+ while(true)
+ {
+ let token=tokenizer.GetNextToken();
+ if (!token) break;
+
+ tokens.push(token);
+ }
+ }
+ catch(e)
+ {
+
+ }
+
+ return tokens;
+}
+
+//语法解析 生成抽象语法树(Abstract Syntax Tree)
+JSComplier.Parse=function(code)
+{
+ JSConsole.Complier.Log('[JSComplier.Parse]',code);
+
+ let parser=new JSParser(code);
+ parser.Initialize();
+ let program=parser.ParseScript();
+ let ast=program;
+ return ast;
+}
+
+/*
+ 执行
+ option.Symbol=股票代码
+ option.Name=股票名称
+ option.Data=这个股票的ChartData
+ option.Right=复权
+ option.MaxReqeustDataCount=请求数据的最大个数
+*/
+
+function timeout(ms) {
+ return new Promise((resolve) => {
+ setTimeout(resolve, ms);
+ });
+ }
+
+
+JSComplier.Execute=function(code,option,errorCallback)
+{
+ //异步调用
+ var asyncExecute= function()
+ {
+ try
+ {
+ JSConsole.Complier.Log('[JSComplier.Execute] code ',code);
+
+ JSConsole.Complier.Log('[JSComplier.Execute] parser .....');
+ let parser=new JSParser(code);
+ parser.Initialize();
+ let program=parser.ParseScript();
+
+ let ast=program;
+ JSConsole.Complier.Log('[JSComplier.Execute] parser finish.', ast);
+
+ JSConsole.Complier.Log('[JSComplier.Execute] execute .....');
+ let execute=new JSExecute(ast,option);
+ execute.JobList=parser.Node.GetDataJobList();
+ execute.JobList.push({ID:JS_EXECUTE_JOB_ID.JOB_RUN_SCRIPT});
+
+ let result=execute.Execute();
+
+ }catch(error)
+ {
+ JSConsole.Complier.Log(error);
+
+ if (errorCallback) errorCallback(error);
+ }
+ }
+
+ asyncExecute();
+
+ JSConsole.Complier.Log('[JSComplier.Execute] async execute.');
+}
+
+JSComplier.SetDomain = function (domain, cacheDomain)
+{
+ if (domain) g_JSComplierResource.Domain = domain;
+ if (cacheDomain) g_JSComplierResource.CacheDomain = cacheDomain;
+}
+
+JSComplier.AddFunction=function(obj) //添加函数 { Name:函数名, Description:描述信息, IsDownload:是否需要下载数据, Invoke:函数执行(可选) }
+{
+ if (!obj || !obj.Name) return;
+
+ var ID=obj.Name.toUpperCase();
+ g_JSComplierResource.CustomFunction.Data.set(ID, obj);
+}
+
+JSComplier.AddVariant=function(obj) //{ Name:变量名, Description:描述信息 }
+{
+ if (!obj || !obj.Name) return;
+
+ var ID=obj.Name.toUpperCase();
+ g_JSComplierResource.CustomVariant.Data.set(ID, obj);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+//数据下载
+function DownloadFinanceData(obj)
+{
+ this.Url=obj.Url;
+ this.RealtimeUrl=obj.RealtimeUrl;
+ this.Job=obj.Job;
+ this.Symbol=obj.Symbol;
+ this.Args=obj.Args;
+ this.DataKey=obj.DataKey;
+ this.RecvCallback=obj.Callback;
+ this.ErrorCallback=obj.ErrorCallback;
+
+ this.Download=function()
+ {
+ var id=this.Args[0];
+ switch(id)
+ {
+ case 1: //FINANCE(1) 总股本(随时间可能有变化) 股
+ case 7: //FINANCE(7) 流通股本(随时间可能有变化) 股
+ case "EXCHANGE": //换手率
+ this.DownloadHistoryData(id);
+ break;
+
+ case 9: //FINANCE(9) 资产负债率
+ case 18: //FINANCE(18) 每股公积金
+ case 30: //FINANCE(30) 净利润
+ case 32: //FINANCE(32) 每股未分配利润
+ case 33: //FINANCE(33) 每股收益(折算为全年收益),对于沪深品种有效
+ case 34: //FINANCE(34) 每股净资产
+ case 38: //FINANCE(38) 每股收益(最近一期季报)
+ case 40: //FINANCE(40) 流通市值
+ case 41: //FINANCE(41) 总市值
+ case 42: //FINANCE(42) 上市的天数
+ case 43: //FINANCE(43) 利润同比
+
+ case "CAPITAL":
+ case "TOTALCAPITAL":
+
+ //定制
+ case 100: //股东人数
+ this.DownloadRealtimeData(id);
+ break;
+
+ default:
+ this.DownloadRealtimeData(id);
+ break;
+ }
+ }
+
+ //最新一期数据
+ this.DownloadRealtimeData=function(id)
+ {
+ var self=this;
+ var fieldList=this.GetFieldList();
+ if (!fieldList)
+ {
+ if (this.Job.FunctionName2) message=`${this.Job.FunctionName2} can't support.`;
+ else if (this.Job.FunctionName) message=`${this.Job.FunctionName}(${this.Args[0]}) can't support.`;
+ else message=`${this.Args[0]} can't support.`;
+ this.ErrorCallback(message);
+ self.RecvCallback(null, self.Job, self.DataKey);
+ return;
+ }
+
+ //请求数据
+ wx.request({
+ url: this.RealtimeUrl,
+ data:
+ {
+ "field": fieldList,
+ "symbol": [this.Symbol],
+ "condition":[ ] ,
+ "start": 0,
+ "end": 10
+ },
+ method: 'POST',
+ dataType: "json",
+ async:true,
+ success: function (recvData)
+ {
+ var data=self.RealtimeDataToHQChartData(recvData.data);
+ self.RecvCallback(data, self.Job, self.DataKey);
+ }
+ });
+ }
+
+ //历史数据
+ this.DownloadHistoryData=function(id)
+ {
+ var self=this;
+ var fieldList=this.GetFieldList();
+ if (!fieldList)
+ {
+ message=`${this.Job.FunctionName}(${this.Args[0]}) can't support.`;
+ this.ErrorCallback(message);
+ self.RecvCallback(null, self.Job, self.DataKey);
+ return;
+ }
+
+ //请求数据
+ wx.request({
+ url: this.Url,
+ data:
+ {
+ "field": fieldList,
+ "symbol": [this.Symbol],
+ "condition":[ ] ,
+ "start": 0,
+ "end": 200
+ },
+ method: 'POST',
+ dataType: "json",
+ async:true,
+ success: function (recvData)
+ {
+ var data=self.ToHQChartData(recvData.data);
+ if (data) //排序
+ data.sort(function (a, b) { return (a.Date - b.Date) });
+
+ self.RecvCallback(data, self.Job, self.DataKey);
+ }
+ });
+ }
+
+ this.GetFieldList=function()
+ {
+ var id=this.Args[0];
+ switch(id)
+ {
+ case 1:
+ return ["capital.total", "capital.date"];
+ case 7:
+ return ["capital.a", "capital.date"];
+ case "EXCHANGE":
+ return ["capital.a", "capital.date"];
+
+ case 9:
+ return ["finance.peruprofit","symbol","date"];
+ case 18:
+ return ["finance.percreserve","symbol","date"];
+ case 30:
+ return ["finance.nprofit","symbol","date"];
+ case 32:
+ return ["finance.peruprofit","symbol","date"];
+ case 33:
+ return ["finance.persearning","symbol","date"];
+ case 34:
+ return ["finance.pernetasset","symbol","date"];
+ case 38:
+ return ["finance.persearning","symbol","date"];
+ case 40:
+ return ["capital.a", "capital.date","symbol","date", "price"];
+ case 41:
+ return ["capital.total", "capital.date","symbol","date","price"];
+ case "CAPITAL":
+ return ["capital.a", "capital.date","symbol","date"];
+ case "TOTALCAPITAL":
+ return ["capital.total", "capital.date","symbol","date"];
+ case 42:
+ return ["company.releasedate","symbol","date"];
+ case 43:
+ return ["dividendyield","symbol","date"];
+ case 100:
+ return ["shareholder","symbol","date"]
+ default:
+ return null;
+ }
+ }
+
+ //最新报告期数据
+ this.RealtimeDataToHQChartData=function(recvData,id)
+ {
+ if (!recvData.stock || recvData.stock.length!=1) return null;
+ var stock=recvData.stock[0];
+ var id=this.Args[0];
+ var date=stock.date;
+ switch(id)
+ {
+ case 9:
+ if (!stock.finance) return null;
+ return { Date:date, Value:stock.finance.peruprofit };
+ case 18:
+ if (!stock.finance) return null;
+ return { Date:date, Value:stock.finance.percreserve };
+ case 30:
+ if (!stock.finance) return null;
+ return { Date:date, Value:stock.finance.nprofit };
+ case 32:
+ if (!stock.finance) return null;
+ return { Date:date, Value:stock.finance.peruprofit };
+ case 33:
+ if (!stock.finance) return null;
+ return { Date:date, Value:stock.finance.persearning };
+ case 34:
+ if (!stock.finance) return null;
+ return { Date:date, Value:stock.finance.pernetasset };
+ case 38:
+ if (!stock.finance) return null;
+ return { Date:date, Value:stock.finance.persearning };
+ case 40: //FINANCE(40) 流通市值
+ if (!stock.capital) return null;
+ return { Date:date, Value:stock.capital.a*stock.price }; //流通股*最新价格
+ case 41: //FINANCE(41) 总市值
+ if (!stock.capital) return null;
+ return { Date:date, Value:stock.capital.total*stock.price }; //总股本*最新价格
+ case 42: //FINANCE(42) 上市的天数
+ if (!stock.company) return null;
+ {
+ var releaseDate=stock.company.releasedate;
+ var year=parseInt(releaseDate/10000);
+ var month=parseInt((releaseDate%10000)/100);
+ var day=releaseDate%100;
+ var firstDate=new Date(year, month-1, day);
+ var nowDate=new Date();
+ var days=parseInt((nowDate.getTime()-firstDate.getTime())/(1000 * 60 * 60 * 24));
+ return { Date:date, Value:days+1 };
+ }
+ case 43:
+ if (!stock.dividendyield) return null;
+ return { Date:date, Value:stock.dividendyield.quarter4 };
+ case 100:
+ if (!stock.shareholder) return null;
+ return { Date:date, Value:stock.shareholder.count };
+ case "CAPITAL":
+ if (!stock.capital) return null;
+ return { Date:date, Value:stock.capital.a/100 }; //当前流通股本 手
+ case "TOTALCAPITAL":
+ if (!stock.capital) return null;
+ return { Date:date, Value:stock.capital.total/100 }; //当前流通股本 手
+ }
+ }
+
+ //历史数据转
+ this.ToHQChartData=function(recvData)
+ {
+ if (!recvData.stock || recvData.stock.length!=1) return null;
+
+ var aryData=[];
+ var setDate=new Set(); //有重复数据 去掉
+ var stock=recvData.stock[0];
+ var id=this.Args[0];
+ for(var i in stock.stockday)
+ {
+ var item=stock.stockday[i];
+
+ var hqchartItem=this.ToHQChartItemData(item,id);
+ if (hqchartItem && !setDate.has(hqchartItem.Date))
+ {
+ aryData.push(hqchartItem);
+ setDate.add(hqchartItem.Date);
+ }
+ }
+
+ return aryData;
+ }
+
+ this.ToHQChartItemData=function(item, id)
+ {
+ if (!item) return null;
+ var date=item.date;
+ switch(id)
+ {
+ case 1:
+ if (!item.capital) return null;
+ return { Date:date, Value:item.capital.total };
+ case 7:
+ case "EXCHANGE": //换手率 历史流通股本
+ if (!item.capital) return null;
+ return { Date:date, Value:item.capital.a };
+
+ default:
+ return null;
+ }
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////
+//内置财务数据下载
+//
+function DownloadFinValueData(obj)
+{
+ this.Url=obj.Url;
+ this.Job=obj.Job;
+ this.Symbol=obj.Symbol;
+ this.Args=obj.Args;
+ this.DataKey=obj.DataKey;
+ this.RecvCallback=obj.Callback;
+ this.ErrorCallback=obj.ErrorCallback;
+
+ this.Download=function()
+ {
+ var self=this;
+ var fieldList=this.GetFieldList();
+ if (!fieldList)
+ {
+ message=`${this.Job.FunctionName}(${this.Args[0]}) can't support.`;
+ this.ErrorCallback(message);
+ self.RecvCallback(null, self.Job, self.DataKey);
+ return;
+ }
+
+ //请求数据
+ wx.request({
+ url: this.Url,
+ data:
+ {
+ "field": fieldList,
+ "symbol": [this.Symbol],
+ "condition":[ {"item":["finance","doc","exists","true"]}] ,
+ "start": 0,
+ "end": 200
+ },
+ method: 'POST',
+ dataType: "json",
+ async:true,
+ success: function (recvData)
+ {
+ var data=self.ToHQChartData(recvData.data);
+ if (data) //排序
+ data.sort(function (a, b) { return (a.Date - b.Date) });
+
+ self.RecvCallback(data, self.Job, self.DataKey);
+ }
+ });
+ }
+
+ this.ToHQChartData=function(recvData)
+ {
+ if (!recvData.stock || recvData.stock.length!=1) return null;
+
+ var aryData=[];
+ var setDate=new Set(); //有重复数据 去掉
+ var stock=recvData.stock[0];
+ for(var i in stock.stockday)
+ {
+ var item=stock.stockday[i];
+ if (item.announcement1)
+ {
+ var hqchartItem=this.ToHQChartItemData(item.announcement1, item.finance1, item);
+ if (hqchartItem && !setDate.has(hqchartItem.Date))
+ {
+ aryData.push(hqchartItem);
+ setDate.add(hqchartItem.Date);
+ }
+ }
+
+ if (item.announcement2)
+ {
+ var hqchartItem=this.ToHQChartItemData(item.announcement2, item.finance2, item);
+ if (hqchartItem && !setDate.has(hqchartItem.Date))
+ {
+ aryData.push(hqchartItem);
+ setDate.add(hqchartItem.Date);
+ }
+ }
+
+ if (item.announcement3)
+ {
+ var hqchartItem=this.ToHQChartItemData(item.announcement3, item.finance3, item);
+ if (hqchartItem && !setDate.has(hqchartItem.Date))
+ {
+ aryData.push(hqchartItem);
+ setDate.add(hqchartItem.Date);
+ }
+ }
+
+ if (item.announcement4)
+ {
+ var hqchartItem=this.ToHQChartItemData(item.announcement4, item.finance4, item);
+ if (hqchartItem && !setDate.has(hqchartItem.Date))
+ {
+ aryData.push(hqchartItem);
+ setDate.add(hqchartItem.Date);
+ }
+ }
+ }
+
+ return aryData;
+ }
+
+ //{ Date:日期 , Value:数值 }
+ this.ToHQChartItemData=function(announcement, finance, sourceItem)
+ {
+ var id=this.Args[0];
+ var date=announcement.year*10000;
+ var quarter=announcement.quarter;
+ switch(quarter)
+ {
+ case 1:
+ date+=331;
+ break;
+ case 2:
+ date+=630;
+ break;
+ case 3:
+ date+=930;
+ break;
+ case 4:
+ date+=1231;
+ break;
+ default:
+ return null;
+ }
+
+ var result={ Date:date, Value:0 };
+ switch(id)
+ {
+ case 0:
+ result.Value=date%1000000; //0--返回报告期(YYMMDD格式),150930表示为2015年第三季
+ break;
+ case 1:
+ result.Value=finance.persearning;
+ break;
+ case 3:
+ result.Value=finance.peruprofit;
+ break;
+ case 4:
+ result.Value=finance.pernetasset;
+ break;
+ case 5:
+ result.Value=finance.percreserve;
+ break;
+ case 6:
+ result.Value=finance.woewa;
+ break;
+ case 7:
+ result.Value=finance.perccfo;
+ break;
+ case 8:
+ result.Value=finance.monetaryfunds;
+ break;
+ case 11:
+ result.Value=finance.areceivable;
+ break;
+ }
+
+ return result;
+ }
+
+ this.GetFieldList=function()
+ {
+ var id=this.Args[0];
+ switch(id)
+ {
+ case 0:
+ return ["finance.date"];
+ case 1: //persearning 每股收益
+ return ["finance.persearning"];
+ case 3: //peruprofit 每股未分配利润
+ return ["finance.peruprofit"];
+ case 4: //pernetasset 每股净资产
+ return ["finance.pernetasset"];
+ case 5: //percreserve 每股资本公积金
+ return ["finance.percreserve"];
+ case 6: //woewa 加权平均净资产收益
+ return ["finance.woewa"];
+ case 7: //perccfo 每股经营性现金流
+ return ["finance.perccfo"];
+ case 8: //monetaryfunds 货币资金
+ return ["finance.monetaryfunds"];
+ case 11: //areceivable 应收账款
+ return ["finance.areceivable"];
+ default:
+ return null;
+ }
+ }
+}
+
+
+/////////////////////////////////////////////////////////
+// 内置财务数据下载 某一期的数据
+//
+function DownloadFinOneData(obj)
+{
+ this.newMethod=DownloadFinValueData; //派生
+ this.newMethod(obj);
+ delete this.newMethod;
+
+ this.Download=function()
+ {
+ var self=this;
+ var fieldList=this.GetFieldList();
+ if (!fieldList)
+ {
+ message=`${this.Job.FunctionName}(${this.Args[0]}, ${this.Args[1]}, ${this.Args[2]}) can't support.`;
+ this.ErrorCallback(message);
+ self.RecvCallback(null, self.Job, self.DataKey);
+ return;
+ }
+
+ var aryCondition=[ {"item":["finance","doc","exists","true"] } ];
+
+ var year=this.Args[1];
+ var month=this.Args[2];
+ var dataIndex=0;
+ var dataEnd=3;
+ var preYear=null;
+ if (year==0 && month==0) //如果Y和MMDD都为0,表示最新的财报;
+ {
+
+ }
+ else if (year==0 && month<300) //如果Y为0,MMDD为小于300的数字,表示最近一期向前推MMDD期的数据,如果是331,630,930,1231这些,表示最近一期的对应季报的数据;
+ {
+ dataIndex=month;
+ dataEnd=200;
+ }
+ else if (month==0 && year<1000) //如果Y为0,MMDD为小于300的数字,表示最近一期向前推MMDD期的数据,如果是331,630,930,1231这些,表示最近一期的对应季报的数据;
+ {
+ preYear=year;
+ }
+ else if (year>1909)
+ {
+ if (month==331)
+ {
+ aryCondition=
+ [
+ {"item":["announcement1.year","int32","eq",year]},
+ {"item":["finance1","doc","exists","true"]}
+ ];
+
+ fieldList.push("announcement1.year");
+ fieldList.push("announcement1.quarter");
+ }
+ else if (month==630)
+ {
+ aryCondition=
+ [
+ {"item":["announcement2.year","int32","eq",year]},
+ {"item":["finance2","doc","exists","true"]}
+ ];
+
+ fieldList.push("announcement2.year");
+ fieldList.push("announcement2.quarter");
+ }
+ else if (month==930)
+ {
+ aryCondition=
+ [
+ {"item":["announcement3.year","int32","eq",year]},
+ {"item":["finance3","doc","exists","true"]}
+ ];
+
+ fieldList.push("announcement4.year");
+ fieldList.push("announcement4.quarter");
+ }
+ else
+ {
+ aryCondition=
+ [
+ {"item":["announcement4.year","int32","eq",year]},
+ {"item":["finance4","doc","exists","true"]}
+ ];
+
+ fieldList.push("announcement4.year");
+ fieldList.push("announcement4.quarter");
+ }
+ }
+
+ //请求数据
+ wx.request({
+ url: this.Url,
+ data:
+ {
+ "field": fieldList,
+ "symbol": [this.Symbol],
+ "condition":aryCondition,
+ "start": 0,
+ "end": dataEnd
+ },
+ method: 'POST',
+ dataType: "json",
+ async:true,
+ success: function (recvData)
+ {
+ var data=self.ToHQChartData(recvData.data);
+ var result=null;
+ if (data && data.length>0)
+ {
+ data.sort(function (a, b) { return (b.Date-a.Date) });
+ if (preYear==null)
+ result=data[dataIndex]; //返回一个数据
+ else
+ result=self.GetPreYearData(data, preYear);
+ }
+ self.RecvCallback(result, self.Job, self.DataKey);
+ }
+ });
+ }
+
+ this.GetPreYearData=function(data, preYear)
+ {
+ //331,630,930,1231这些,表示最近一期的对应季报的数据;
+ if (preYear==331 || preYear==630|| preYear==930 || preYear==1231)
+ {
+ for(var i in data)
+ {
+ var item=data[i];
+ if (item.Date%10000==preYear) return item;
+ }
+ }
+ else
+ {
+ //如果MMDD为0,Y为一数字,表示最近一期向前推Y年的同期数据;
+ var month=data[0].Date%1000;
+ for(var i=1, j=0; i0)
+ {
+ data.sort(function (a, b) { return (a.Date-b.Date) });
+ }
+ self.RecvCallback(data, self.Job, self.DataKey);
+ }
+ });
+ }
+
+ this.GetFieldList=function()
+ {
+ var id=this.Args[0];
+ switch(id)
+ {
+ case 1: //1--股东人数 股东户数(户)
+ return ["shareholder", "date", "symbol"];
+ case 2: //2--龙虎榜 买入总计(万元) 卖出总计(万元)
+ return ["tradedetail.buy","tradedetail.sell", "date", "symbol"];
+ case 3: //3--融资融券1 融资余额(万元) 融券余量(股)
+ return ["margin","date", "symbol"];
+ case 4: //4--大宗交易 成交均价(元) 成交额(万元)
+ return ["blocktrading.amount","blocktrading.price","date", "symbol"]
+ default:
+ return null;
+ }
+ }
+
+ this.ToHQChartData=function(recvData)
+ {
+ if (!recvData.stock || recvData.stock.length!=1) return null;
+
+ var aryData=[];
+ var setDate=new Set(); //有重复数据 去掉
+ var stock=recvData.stock[0];
+ var id=this.Args[0];
+ var subID=this.Args[1];
+ for(var i in stock.stockday)
+ {
+ var item=stock.stockday[i];
+
+ var hqchartItem=this.ToHQChartItemData(item,id,subID);
+ if (hqchartItem && !setDate.has(hqchartItem.Date))
+ {
+ aryData.push(hqchartItem);
+ setDate.add(hqchartItem.Date);
+ }
+ }
+
+ return aryData;
+ }
+
+ this.ToHQChartItemData=function(item, id, subID)
+ {
+ if (!item) return null;
+ var date=item.date;
+ switch(id)
+ {
+ case 1:
+ if (!item.shareholder) return null;
+ return { Date:date, Value:item.shareholder.count };
+ case 2:
+ if (!item.tradedetail && item.tradedetail[0]) return null;
+ if (subID==0)
+ return { Date:date, Value:item.tradedetail[0].buy };
+ else
+ return { Date:date, Value:item.tradedetail[0].sell };
+ case 3:
+ if (!item.margin) return null;
+ if (subID==0)
+ {
+ if (item.margin.buy)
+ return { Date:date, Value:item.margin.buy.balance };
+ }
+ else
+ {
+ if (item.margin.sell)
+ return { Date:date, Value:item.margin.sell.balance };
+ }
+ return null;
+ case 4:
+ if (!item.blocktrading) return null;
+ if (subID==0)
+ return { Date:date, Value:item.blocktrading.price };
+ else
+ return { Date:date, Value:item.blocktrading.amount };
+ default:
+ return null;
+ }
+ }
+}
+
+function DownloadGroupData(obj)
+{
+ this.Url=obj.Url;
+ this.RealtimeUrl=obj.RealtimeUrl;
+ this.Job=obj.Job;
+ this.Symbol=obj.Symbol;
+ this.Args=obj.Args;
+ this.DataKey=obj.DataKey;
+ this.RecvCallback=obj.Callback;
+ this.ErrorCallback=obj.ErrorCallback;
+
+ this.Download=function()
+ {
+ var varName=this.Args[0];
+ switch(varName)
+ {
+ case "HYBLOCK":
+ case "DYBLOCK":
+ case "GNBLOCK":
+ this.DownloadGroupName(varName);
+ break;
+ }
+ }
+
+ this.DownloadGroupName=function(blockType)
+ {
+ var self=this;
+ var field=["name","symbol"];
+ if (blockType=="HYBLOCK") field.push("industry");
+ else if (blockType=="DYBLOCK") field.push("region");
+ else if (blockType=="GNBLOCK") field.push("concept");
+
+ wx.request({
+ url: self.RealtimeUrl,
+ data:
+ {
+ "field": field,
+ "symbol": [this.Symbol]
+ },
+ method:"post",
+ dataType: "json",
+ async:true,
+ success: function (recvData)
+ {
+ var data=self.RecvGroupName(recvData.data);
+ self.RecvCallback(data, self.Job, self.DataKey, 1);
+ },
+ error: function(request)
+ {
+ self.ErrorCallback(request);
+ }
+ });
+ }
+
+ this.RecvGroupName=function(recvData)
+ {
+ if (!recvData.stock || recvData.stock.length!=1) return null;
+ var stock=recvData.stock[0];
+ var varName=this.Args[0];
+ var value=null;
+ if (varName=="HYBLOCK")
+ {
+ var industry=stock.industry;
+ if (!industry) return null;
+ var value;
+ for(var i in industry)
+ {
+ var item=industry[i];
+ value=item.name;
+ }
+ }
+ else if (varName=="DYBLOCK")
+ {
+ var region=stock.region;
+ if (!region) return null;
+ for(var i in region)
+ {
+ var item=region[i];
+ value=item.name;
+ }
+ }
+ else if (varName=="GNBLOCK")
+ {
+ var concept=stock.concept;
+ if (!concept) return null;
+ value="";
+ for(var i in concept)
+ {
+ var item=concept[i];
+ if (value.length>0) value+=' ';
+ value+=item.name;
+ }
+
+ }
+
+ return { Value:value };
+ }
+}
+
+/* 测试例子
+var code1='VARHIGH:IF(VAR1<=REF(HH,-1),REF(H,BARSLAST(VAR1>=REF(HH,1))),DRAWNULL),COLORYELLOW;';
+var code2='VAR1=((SMA(MAX((CLOSE - LC),0),3,1) / SMA(ABS((CLOSE - LC)),3,1)) * 100);';
+var code3='mm1=1-2*-9+20;';
+
+JSConsole.Complier.Log(code1+code2)
+var tokens=JSComplier.Tokenize(code1+code2);
+var ast=JSComplier.Parse(code2+code1);
+
+JSConsole.Complier.Log(ast);
+*/
+
+
+module.exports =
+{
+ JSCommonComplier:
+ {
+ JSComplier: JSComplier,
+ },
+
+ //单个类导出
+ JSCommonComplier_ErrorHandler: ErrorHandler,
+ JSCommonComplier_JSComplier:JSComplier,
+ JSCommonComplier_JSParser:JSParser,
+ JSCommonComplier_Syntax:Syntax,
+ JS_EXECUTE_JOB_ID:JS_EXECUTE_JOB_ID,
+ g_JSComplierResource:g_JSComplierResource,
+};
\ No newline at end of file
diff --git a/uni_modules/jones-hqchart2/js_sdk/umychart.console.wechat.js b/uni_modules/jones-hqchart2/js_sdk/umychart.console.wechat.js
new file mode 100644
index 0000000..9bdea83
--- /dev/null
+++ b/uni_modules/jones-hqchart2/js_sdk/umychart.console.wechat.js
@@ -0,0 +1,15 @@
+//日志输出类
+var JSConsole=
+{
+ Chart:{ Log:console.log, Warn:console.warn }, //图形日志
+ Complier:{ Log:console.log, Warn:console.warn }, //编译器日志
+};
+
+module.exports =
+{
+ JSConsole:
+ {
+ Chart: JSConsole.Chart,
+ Complier:JSConsole.Complier
+ }
+};
\ No newline at end of file
diff --git a/uni_modules/jones-hqchart2/js_sdk/umychart.coordinatedata.wechat.js b/uni_modules/jones-hqchart2/js_sdk/umychart.coordinatedata.wechat.js
new file mode 100644
index 0000000..2eff188
--- /dev/null
+++ b/uni_modules/jones-hqchart2/js_sdk/umychart.coordinatedata.wechat.js
@@ -0,0 +1,2443 @@
+/*
+ copyright (c) 2018 jones
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ 开源项目 https://github.com/jones2000/HQChart
+
+ jones_2000@163.com
+
+ 各个品种分钟走势图坐标信息
+*/
+
+function GetLocalTime(i) //得到标准时区的时间的函数
+{
+ if (typeof i !== 'number') return;
+ var d = new Date();
+ //得到1970年一月一日到现在的秒数
+ var len = d.getTime();
+ //本地时间与GMT时间的时间偏移差
+ var offset = d.getTimezoneOffset() * 60000;
+ //得到现在的格林尼治时间
+ var utcTime = len + offset;
+ return new Date(utcTime + 3600000 * i);
+}
+
+var MARKET_SUFFIX_NAME=
+{
+ SH:'.SH',
+ SZ:'.SZ',
+ SHSZ_C_Index:'.CI', //自定义指数
+ SHO:'.SHO', //上海交易所 股票期权
+ HK:'.HK',
+ FHK: '.FHK', //港股期货
+ SHFE: '.SHF', //上期所 (Shanghai Futures Exchange)
+ SHFE2: '.SHFE', //上期所 (Shanghai Futures Exchange)
+ CFFEX: '.CFE', //中期所 (China Financial Futures Exchange)
+ DCE: '.DCE', //大连商品交易所(Dalian Commodity Exchange)
+ CZCE: '.CZC', //郑州期货交易所
+ USA: '.USA', //美股
+ FTSE: '.FTSE', //富时中国
+
+ BIT: '.BIT', //数字货币 如比特币
+ BIZ: '.BIZ', //数字货币
+
+ NYMEX: '.NYMEX', //纽约商品期货交易所(New York Mercantile Exchange)
+ COMEX: ".COMEX", //纽约商品期货交易所(New York Mercantile Exchange)
+ NYBOT: ".NYBOT", //美國紐約商品交易所
+ CBOT: ".CBOT", //芝商所
+
+ LME: ".LME", //伦敦金属交易所
+
+ ET: '.ET', //其他未知的品种
+
+ IsET: function (upperSymbol)
+ {
+ if (!upperSymbol) return false;
+ return upperSymbol.indexOf(this.ET) > 0;
+ },
+
+ IsETShowAvPrice: function (upperSymbol) //是否显示均价
+ {
+ return false;
+ },
+
+ IsNYMEX: function (upperSymbol)
+ {
+ if (!upperSymbol) return false;
+ return upperSymbol.indexOf(this.NYMEX) > 0;
+ },
+
+ IsCOMEX: function (upperSymbol)
+ {
+ if (!upperSymbol) return false;
+ return upperSymbol.indexOf(this.COMEX) > 0;
+ },
+
+ IsNYBOT: function (upperSymbol)
+ {
+ if (!upperSymbol) return false;
+ return upperSymbol.indexOf(this.NYBOT) > 0;
+ },
+
+ IsCBOT: function (upperSymbol)
+ {
+ if (!upperSymbol) return false;
+ return upperSymbol.indexOf(this.CBOT) > 0;
+ },
+
+ IsLME: function (upperSymbol)
+ {
+ if (!upperSymbol) return false;
+ return upperSymbol.indexOf(this.LME) > 0;
+ },
+
+ IsFTSE: function (upperSymbol)
+ {
+ if (!upperSymbol) return false;
+ return upperSymbol.indexOf(this.FTSE) > 0;
+ },
+
+ IsFHK: function (upperSymbol)
+ {
+ if (!upperSymbol) return false;
+ return upperSymbol.indexOf(this.FHK) > 0;
+ },
+
+ IsBIT: function (upperSymbol)
+ {
+ if (!upperSymbol) return false;
+ if (upperSymbol.indexOf(this.BIT) > 0) return true;
+ if (upperSymbol.indexOf(this.BIZ) > 0) return true;
+ return false;
+ },
+
+ IsUSA: function (upperSymbol) //是否是美股
+ {
+ if (!upperSymbol) return false;
+ return upperSymbol.indexOf(this.USA) > 0;
+ },
+
+ IsSH: function (upperSymbol)
+ {
+ //需要精确匹配最后3位
+ var pos = upperSymbol.length-this.SH.length;
+ var find = upperSymbol.indexOf(this.SH);
+ return find == pos;
+ },
+
+ IsSZ: function (upperSymbol)
+ {
+ var pos = upperSymbol.length - this.SZ.length;
+ var find = upperSymbol.indexOf(this.SZ);
+ return find == pos;
+ },
+
+ //自定义指数
+ IsSHSZCustomIndex:function(upperSymbol)
+ {
+ var pos = upperSymbol.length - this.SHSZ_C_Index.length;
+ var find = upperSymbol.indexOf(this.SHSZ_C_Index);
+ return find == pos;
+ },
+
+ IsSHO: function (upperSymbol)
+ {
+ var pos = upperSymbol.length - this.SHO.length;
+ var find = upperSymbol.indexOf(this.SHO);
+ return find == pos;
+ },
+
+ IsHK: function (upperSymbol)
+ {
+ var pos = upperSymbol.length - this.HK.length;
+ var find = upperSymbol.indexOf(this.HK);
+ return find == pos;
+ },
+
+ IsSHFE: function (upperSymbol)
+ {
+ if (!upperSymbol) return false;
+ if (upperSymbol.indexOf(this.SHFE) > 0) return true;
+ if (upperSymbol.indexOf(this.SHFE2) > 0) return true;
+ return false;
+ },
+
+ IsCFFEX: function (upperSymbol)
+ {
+ if (!upperSymbol) return false;
+ return upperSymbol.indexOf(this.CFFEX) > 0;
+ },
+
+ IsDCE: function (upperSymbol)
+ {
+ if (!upperSymbol) return false;
+ return upperSymbol.indexOf(this.DCE) > 0;
+ },
+
+ IsCZCE: function (upperSymbol)
+ {
+ if (!upperSymbol) return false;
+ return upperSymbol.indexOf(this.CZCE) > 0;
+ },
+
+ IsChinaFutures: function (upperSymbol) //是否是国内期货
+ {
+ return this.IsCFFEX(upperSymbol) || this.IsCZCE(upperSymbol) || this.IsDCE(upperSymbol) || this.IsSHFE(upperSymbol);
+ },
+
+ IsFutures: function (upperSymbol) //是否是期货 包含国外的
+ {
+ return this.IsChinaFutures(upperSymbol) ||
+ this.IsNYMEX(upperSymbol) || this.IsCOMEX(upperSymbol) || this.IsNYBOT(upperSymbol) || this.IsCBOT(upperSymbol) ||
+ this.IsLME(upperSymbol);
+ },
+
+ IsSHSZ: function (upperSymbol) //是否是沪深的股票
+ {
+ return this.IsSZ(upperSymbol) || this.IsSH(upperSymbol) || this.IsSHSZCustomIndex(upperSymbol);
+ },
+
+ IsSHSZFund: function (upperSymbol) //是否是交易所基金
+ {
+ if (!upperSymbol) return false;
+
+ if (this.IsSH(upperSymbol)) //51XXXX.SH
+ {
+ if (upperSymbol.charAt(0) == '5' && upperSymbol.charAt(1) == '1') return true;
+ }
+ else if (this.IsSZ(upperSymbol)) //15XXXX.sz, 16XXXX.sz, 17XXXX.sz, 18XXXX.sz
+ {
+ if (upperSymbol.charAt(0) == '1' &&
+ (upperSymbol.charAt(1) == '5' || upperSymbol.charAt(1) == '6' || upperSymbol.charAt(1) == '7' || upperSymbol.charAt(1) == '8')) return true;
+ }
+
+ return false;
+ },
+
+ IsSHSZIndex: function (symbol) //是否是沪深指数代码
+ {
+ if (!symbol) return false;
+
+ var upperSymbol = symbol.toUpperCase();
+ if (this.IsSH(upperSymbol))
+ {
+ var temp = upperSymbol.replace('.SH', '');
+ if (upperSymbol.charAt(0) == '0' && parseInt(temp) <= 3000) return true;
+
+ }
+ else if (this.IsSZ(upperSymbol))
+ {
+ if (upperSymbol.charAt(0) == '3' && upperSymbol.charAt(1) == '9') return true;
+ }
+ else if (this.IsSHSZCustomIndex(upperSymbol)) //自定义指数
+ {
+ return true;
+ }
+
+ return false;
+ },
+
+ IsSHSZStockA: function (symbol) //是否是沪深A股
+ {
+ if (!symbol) return false;
+ var upperSymbol = symbol.toUpperCase();
+ if (this.IsSH(upperSymbol))
+ {
+ var temp = upperSymbol.replace('.SH', '');
+ if (upperSymbol.charAt(0) == '6') return true;
+ }
+ else if (this.IsSZ(upperSymbol))
+ {
+ if (upperSymbol.charAt(0) == '0')
+ {
+ if (upperSymbol.charAt(1) == '0' && upperSymbol.charAt(2) == '2') return true; //002 中小板
+ if (upperSymbol.charAt(1) != '7' && upperSymbol.charAt(1) != '8') return true;
+ }
+ }
+
+ return false;
+ },
+
+ IsSHStockSTAR: function (symbol) // 是否是科创板 Sci-Tech innovAtion boaRd (STAR Market)
+ {
+ if (!symbol) return false;
+ var upperSymbol = symbol.toUpperCase();
+ if (!this.IsSH(upperSymbol)) return false;
+ if (upperSymbol.charAt(0) == '6' && upperSymbol.charAt(1) == '8' && upperSymbol.charAt(2) == '8')
+ return true;
+
+ return false;
+ },
+
+ GetMarketStatus: function (symbol) //获取市场状态 0=闭市 1=盘前 2=盘中 3=盘后
+ {
+ if (!symbol) return 0;
+ var upperSymbol = symbol.toUpperCase();
+ var nowDate = new Date();
+ var day = nowDate.getDay();
+ var time = nowDate.getHours() * 100 + nowDate.getMinutes();
+
+ if (this.IsUSA(upperSymbol))
+ {
+ var usaDate = GetLocalTime(-4);
+ var day = usaDate.getDay();
+ var time = usaDate.getHours() * 100 + usaDate.getMinutes();
+ if (day == 6 || day == 0) return 0; //周末
+
+ //9:30 - 16:00 考虑夏令时间时间增加1小时 9:30 - 17:00
+ if (time > 1730) return 3;
+ if (time < 930) return 1;
+
+ return 2;
+ }
+ else if (this.IsBIT(upperSymbol)) //数字货币24小时
+ {
+ return 2;
+ }
+ else if (this.IsFTSE(upperSymbol)) //富时中国 9:00-16:30 17:00-04:45
+ {
+ if (day == 6 || day == 0) return 0; //周末
+ if (time >= 830 && time <= 2359) return 2;
+ if (time >= 0 && time <= 500) return 2;
+ return 0;
+ }
+ else if (this.IsFHK(upperSymbol)) //港股指数期货 9:15-12:00 13:00-16:30 17:15-01:00
+ {
+ if (day == 6 || day == 0) return 0; //周末
+ if (time >= 900 && time <= 2359) return 2;
+ if (time >= 0 && time <= 120) return 2;
+ return 0;
+ }
+ else if (this.IsET(upperSymbol))
+ {
+ return this.GetETMarketStatus(symbol);
+ }
+ else if (this.IsHK(upperSymbol)) //港股
+ {
+ if (day == 6 || day == 0) return 0; //周末
+ if (time > 1630) return 3;
+ if (time < 925) return 1;
+ return 2;
+ }
+ else if (this.IsNYMEX(upperSymbol))
+ {
+ return this.GetNYMEXMarketStatus(upperSymbol);
+ }
+ else if (this.IsCOMEX(upperSymbol))
+ {
+ return this.GetCOMEXMarketStatus(upperSymbol);
+ }
+ else if (this.IsNYBOT(upperSymbol))
+ {
+ return this.GetNYBOTMarketStatus(upperSymbol);
+ }
+ else if (this.IsCBOT(upperSymbol))
+ {
+ return this.GetCBOTMarketStatus(upperSymbol);
+ }
+ else if (this.IsChinaFutures(upperSymbol)) //国内期货
+ {
+ if(day == 6 || day== 0) return 0; //周末
+
+ //21:00-2:30
+ if(time>=2100) return 2;
+ if (time<=240) return 2;
+
+ //8:55-11:30, 13:00-15:00
+ if(time>=830 && time<=1510) return 2;
+
+ return 1;
+ }
+ else //9:30 - 15:40
+ {
+ if (day == 6 || day == 0) return 0; //周末
+ if (time > 1540) return 3;
+ if (time < 925) return 1;
+ return 2;
+ }
+
+ },
+
+ GetDefaultDecimal:function(symbol)
+ {
+ return 2;
+ },
+
+ GetFHKDecimal: function (symbol) //港股指数期货 小数位数
+ {
+ return 0;
+ },
+
+ GetFTSEDecimal: function (symbol) //富时中国A50期货 小数位数
+ {
+ return 0;
+ },
+
+ GetBITDecimal: function (symbol)
+ {
+ return 2;
+ },
+
+ GetETDecimal: function (symbol)
+ {
+ return 2;
+ },
+
+ GetSHODecimal: function (symbol)
+ {
+ return 4;
+ },
+
+ GetNYMEXDecimal: function (symbol) //纽约期货交易所
+ {
+ return g_NYMEXTimeData.GetDecimal(symbol);
+ },
+
+ GetCOMEXDecimal:function(symbol)
+ {
+ return g_COMEXTimeData.GetDecimal(symbol);
+ },
+
+ GetNYBOTDecimal:function(symbol)
+ {
+ return g_NYBOTTimeData.GetDecimal(symbol);
+ },
+
+ GetCBOTDecimal:function(symbol)
+ {
+ return g_CBOTTimeData.GetDecimal(symbol);
+ },
+
+ GetLMEDecimal:function(symbol)
+ {
+ return g_LMETimeData.GetDecimal(symbol);
+ },
+
+ GetETMarketStatus: function (symbol)
+ {
+ // 0=闭市 1=盘前 2=盘中 3=盘后
+ return 2;
+ },
+
+ GetCOMEXMarketStatus:function(symbol)
+ {
+ return g_COMEXTimeData.GetMarketStatus(symbol);
+ },
+
+ GetNYBOTMarketStatus:function(symbol)
+ {
+ return g_NYBOTTimeData.GetMarketStatus(symbol);
+ },
+
+ GetCBOTMarketStatus:function(symbol)
+ {
+ return g_CBOTTimeData.GetMarketStatus(symbol);
+ },
+
+ GetNYMEXMarketStatus: function (symbol)
+ {
+ return g_NYMEXTimeData.GetMarketStatus(symbol);
+ },
+
+ GetLimitPriceRange:function(symbol, name) //涨停范围
+ {
+ if (!this.IsSHSZStockA(symbol)) return null;
+ if (this.IsSHStockSTAR(symbol)) return {Max:0.2 , Min:-0.2}; //科创板 [20%- -20%]
+
+ if (!name) return null;
+ if (name.indexOf('ST')>=0) return { Max:0.05, Min:-0.05 }; //ST 股票 [5% - -5%]
+
+ return {Max:0.1 , Min:-0.1}; //[10% - -10%]
+ },
+}
+
+
+//走势图分钟数据对应的时间
+function MinuteTimeStringData()
+{
+ this.SHSZ = null; //上海深证交易所时间
+ this.HK = null; //香港交易所时间
+ this.Futures=new Map(); //期货交易时间 key=时间名称 Value=数据
+ this.USA = null; //美股交易时间
+ this.FTSE = null; //富时中国
+ this.FHK = null; //港股指数期货
+ this.BIT=null; //数字货币
+
+ this.Initialize = function () //初始化 默认只初始化沪深的 其他市场动态生成
+ {
+ //this.SHSZ = this.CreateSHSZData();
+ //this.HK = this.CreateHKData();
+ }
+
+ this.GetET = function (upperSymbol) //当天所有的分钟
+ {
+ throw { Name: 'MinuteTimeStringData::GetET', Error: 'not implement' };
+ }
+
+ this.GetSHSZ=function() //动态创建
+ {
+ if (!this.SHSZ) this.SHSZ=this.CreateSHSZData();
+ return this.SHSZ;
+ }
+
+ this.GetSHO = function ()
+ {
+ if (!this.SHO) this.SHO = this.CreateSHOData();
+ return this.SHO;
+ }
+
+ this.GetHK=function()
+ {
+ if (!this.HK) this.HK = this.CreateHKData();
+ return this.HK;
+ }
+
+ this.GetFutures=function(splitData)
+ {
+ if (!this.Futures.has(splitData.Name))
+ {
+ var data = this.CreateTimeData(splitData.Data);
+ this.Futures.set(splitData.Name,data);
+ }
+
+ return this.Futures.get(splitData.Name);
+ }
+
+ this.GetUSA=function()
+ {
+ if (!this.USA) this.USA=this.CreateUSAData();
+ return this.USA;
+ }
+
+ this.GetFTSE = function ()
+ {
+ if (!this.FTSE) this.FTSE = this.CreateFTSEData();
+ return this.FTSE;
+ }
+
+ this.GetFHK = function ()
+ {
+ if (!this.FHK) this.FHK = this.CreateFHKData();
+ return this.FHK;
+ }
+
+ this.GetBIT=function(upperSymbol)
+ {
+ if (!this.BIT) this.BIT=this.CreateBITData();
+ return this.BIT;
+ }
+
+ this.CreateSHSZData = function ()
+ {
+ const TIME_SPLIT =
+ [
+ { Start: 925, End: 925 },
+ { Start: 930, End: 1130 },
+ { Start: 1300, End: 1500 }
+ ];
+
+ return this.CreateTimeData(TIME_SPLIT);
+ }
+
+ this.CreateSHOData = function ()
+ {
+ const TIME_SPLIT =
+ [
+ { Start: 930, End: 1129 },
+ { Start: 1300, End: 1500 }
+ ];
+
+ return this.CreateTimeData(TIME_SPLIT);
+ }
+
+ this.CreateHKData = function ()
+ {
+ const TIME_SPLIT =
+ [
+ { Start: 930, End: 1200 },
+ { Start: 1300, End: 1600 }
+ ];
+
+ return this.CreateTimeData(TIME_SPLIT);
+ }
+
+ this.CreateUSAData=function()
+ {
+ //美国夏令时
+ const TIME_SUMMER_SPLIT =
+ [
+ { Start: 2130, End: 2359 },
+ { Start: 0, End: 400 }
+ ];
+
+ //非夏令时
+ const TIME_SPLIT =
+ [
+ { Start: 2230, End: 2359 },
+ { Start: 0, End: 500 }
+ ];
+
+ //使用美国本地时间
+ const TIME_LOCAL_SPLIT =
+ [
+ { Start: 930, End: 1600 } //美国东部时间9:30到16:00
+ ];
+
+ return this.CreateTimeData(TIME_LOCAL_SPLIT);
+ }
+
+ this.CreateFTSEData = function ()
+ {
+ const TIME_SPLIT =
+ [
+ { Start: 1700, End: 2359 },
+ { Start: 0, End: 445 },
+ { Start: 900, End: 1630 }
+ ];
+
+ return this.CreateTimeData(TIME_SPLIT);
+ }
+
+ this.CreateFHKData = function ()
+ {
+ //港股指数期货 9:15-12:00 13:00-16:30 17:15-01:00
+ const TIME_SPLIT =
+ [
+ { Start: 1715, End: 2359 },
+ { Start: 0, End: 100 },
+ { Start: 915, End: 1200 },
+ { Start: 1300, End: 1630 },
+ ];
+
+ return this.CreateTimeData(TIME_SPLIT);
+ }
+
+ this.CreateBITData=function()
+ {
+ //数字货币 7:00 - 6:59
+ const TIME_SPLIT=
+ [
+ { Start:600, End:2359 },
+ { Start:0, End:559 },
+ ];
+
+ return this.CreateTimeData(TIME_SPLIT);
+ }
+
+ this.CreateTimeData = function (timeSplit)
+ {
+ var data = [];
+ for (var i in timeSplit)
+ {
+ var item = timeSplit[i];
+ for (var j = item.Start; j <= item.End; ++j)
+ {
+ if (j % 100 >= 60) continue; //大于60分钟的数据去掉
+ data.push(j);
+ }
+ }
+ return data;
+ }
+
+ this.GetTimeData = function (symbol)
+ {
+ if (!symbol) return this.SHSZ;
+
+ var upperSymbol = symbol.toLocaleUpperCase(); //转成大写
+ if (MARKET_SUFFIX_NAME.IsSH(upperSymbol) || MARKET_SUFFIX_NAME.IsSZ(upperSymbol) || MARKET_SUFFIX_NAME.IsSHSZIndex(upperSymbol)) return this.GetSHSZ();
+ if (MARKET_SUFFIX_NAME.IsHK(upperSymbol)) return this.GetHK();
+ if (MARKET_SUFFIX_NAME.IsCFFEX(upperSymbol) || MARKET_SUFFIX_NAME.IsCZCE(upperSymbol) || MARKET_SUFFIX_NAME.IsDCE(upperSymbol) || MARKET_SUFFIX_NAME.IsSHFE(upperSymbol))
+ {
+ var splitData = g_FuturesTimeData.GetSplitData(upperSymbol);
+ if (!splitData) return null;
+ return this.GetFutures(splitData);
+ }
+ if (MARKET_SUFFIX_NAME.IsFTSE(upperSymbol)) return this.GetFTSE();
+ if (MARKET_SUFFIX_NAME.IsFHK(upperSymbol)) return this.GetFHK();
+ if (MARKET_SUFFIX_NAME.IsET(upperSymbol)) return this.GetET(upperSymbol);
+ if (MARKET_SUFFIX_NAME.IsBIT(upperSymbol)) return this.GetBIT(upperSymbol);
+
+ if (MARKET_SUFFIX_NAME.IsNYMEX(upperSymbol)) //纽约期货交易所
+ {
+ var splitData = g_NYMEXTimeData.GetSplitData(upperSymbol);
+ if (!splitData) return null;
+ return this.GetFutures(splitData);
+ }
+
+ if (MARKET_SUFFIX_NAME.IsCOMEX(upperSymbol)) //纽约期货交易所
+ {
+ var splitData = g_COMEXTimeData.GetSplitData(upperSymbol);
+ if (!splitData) return null;
+ return this.GetFutures(splitData);
+ }
+
+ if (MARKET_SUFFIX_NAME.IsNYBOT(upperSymbol)) //纽约期货交易所
+ {
+ var splitData = g_NYBOTTimeData.GetSplitData(upperSymbol);
+ if (!splitData) return null;
+ return this.GetFutures(splitData);
+ }
+
+ if (MARKET_SUFFIX_NAME.IsCBOT(upperSymbol)) //芝商所
+ {
+ var splitData = g_CBOTTimeData.GetSplitData(upperSymbol);
+ if (!splitData) return null;
+ return this.GetFutures(splitData);
+ }
+
+ if (MARKET_SUFFIX_NAME.IsLME(upperSymbol)) //伦敦LME
+ {
+ var splitData = g_LMETimeData.GetSplitData(upperSymbol);
+ if (!splitData) return null;
+ return this.GetFutures(splitData);
+ }
+ }
+}
+
+//走势图刻度分钟线
+function MinuteCoordinateData()
+{
+ //沪深走势图时间刻度
+ const SHZE_MINUTE_X_COORDINATE =
+ {
+ Full: //完整模式
+ [
+ [0, 0, "rgb(200,200,200)", "09:30"],
+ [31, 0, "RGB(200,200,200)", "10:00"],
+ [61, 0, "RGB(200,200,200)", "10:30"],
+ [91, 0, "RGB(200,200,200)", "11:00"],
+ [122, 1, "RGB(200,200,200)", "13:00"],
+ [152, 0, "RGB(200,200,200)", "13:30"],
+ [182, 0, "RGB(200,200,200)", "14:00"],
+ [212, 0, "RGB(200,200,200)", "14:30"],
+ [242, 1, "RGB(200,200,200)", "15:00"], // 15:00
+ ],
+ Simple: //简洁模式
+ [
+ [0, 0, "rgb(200,200,200)", "09:30"],
+ [61, 0, "RGB(200,200,200)", "10:30"],
+ [122, 1, "RGB(200,200,200)", "13:00"],
+ [182, 0, "RGB(200,200,200)", "14:00"],
+ [242, 1, "RGB(200,200,200)", "15:00"]
+ ],
+ Min: //最小模式
+ [
+ [0, 0, "rgb(200,200,200)", "09:30"],
+ [122, 1, "RGB(200,200,200)", "13:00"],
+ [242, 1, "RGB(200,200,200)", "15:00"]
+ ],
+
+ Count: 243,
+ MiddleCount: 122,
+
+ GetData: function (width)
+ {
+ if (width < 200) return this.Min;
+ else if (width < 400) return this.Simple;
+
+ return this.Full;
+ }
+ };
+
+ //上海股票期权时间刻度
+ const SHO_MINUTE_X_COORDINATE =
+ {
+ Full: //完整模式
+ [
+ [0, 0, "rgb(200,200,200)", "09:30"],
+ [30, 0, "RGB(200,200,200)", "10:00"],
+ [60, 0, "RGB(200,200,200)", "10:30"],
+ [90, 0, "RGB(200,200,200)", "11:00"],
+ [120, 1, "RGB(200,200,200)", "13:00"],
+ [150, 0, "RGB(200,200,200)", "13:30"],
+ [180, 0, "RGB(200,200,200)", "14:00"],
+ [210, 0, "RGB(200,200,200)", "14:30"],
+ [240, 1, "RGB(200,200,200)", "15:00"], // 15:00
+ ],
+ Simple: //简洁模式
+ [
+ [0, 0, "rgb(200,200,200)", "09:30"],
+ [60, 0, "RGB(200,200,200)", "10:30"],
+ [120, 1, "RGB(200,200,200)", "13:00"],
+ [180, 0, "RGB(200,200,200)", "14:00"],
+ [240, 1, "RGB(200,200,200)", "15:00"]
+ ],
+ Min: //最小模式
+ [
+ [0, 0, "rgb(200,200,200)", "09:30"],
+ [120, 1, "RGB(200,200,200)", "13:00"],
+ [240, 1, "RGB(200,200,200)", "15:00"]
+ ],
+
+ Count: 241,
+ MiddleCount: 120,
+
+ GetData: function (width) {
+ if (width < 200) return this.Min;
+ else if (width < 400) return this.Simple;
+
+ return this.Full;
+ }
+ };
+
+ //港股走势图时间刻度
+ const HK_MINUTE_X_COORDINATE =
+ {
+ Full: //完整模式
+ [
+ [0, 1, "RGB(200,200,200)", "09:30"],
+ [30, 0, "RGB(200,200,200)", "10:00"],
+ [60, 1, "RGB(200,200,200)", "10:30"],
+ [90, 0, "RGB(200,200,200)", "11:00"],
+ [120, 1, "RGB(200,200,200)", "11:30"],
+ [151, 0, "RGB(200,200,200)", "13:00"],
+ [181, 1, "RGB(200,200,200)", "13:30"],
+ [211, 0, "RGB(200,200,200)", "14:00"],
+ [241, 1, "RGB(200,200,200)", "14:30"],
+ [271, 0, "RGB(200,200,200)", "15:00"],
+ [301, 1, "RGB(200,200,200)", "15:30"],
+ [331, 1, "RGB(200,200,200)", "16:00"]
+ ],
+ Simple: //简洁模式
+ [
+ [0, 1, "RGB(200,200,200)", "09:30"],
+ [60, 1, "RGB(200,200,200)", "10:30"],
+ [120, 1, "RGB(200,200,200)", "11:30"],
+ [211, 0, "RGB(200,200,200)", "14:00"],
+ [271, 0, "RGB(200,200,200)", "15:00"],
+ [331, 1, "RGB(200,200,200)", "16:00"]
+ ],
+ Min: //最小模式
+ [
+ [0, 1, "RGB(200,200,200)", "09:30"],
+ [151, 0, "RGB(200,200,200)", "13:00"],
+ [331, 1, "RGB(200,200,200)", "16:00"]
+ ],
+
+ Count: 332,
+ MiddleCount: 151,
+
+ GetData: function (width)
+ {
+ if (width < 200) return this.Min;
+ else if (width < 450) return this.Simple;
+
+ return this.Full;
+ }
+ };
+
+ //富时中国
+ const FTSE_MINUTE_X_COORDINATE =
+ {
+ Full: //完整模式
+ [
+ [0, 1, "RGB(200,200,200)", "17:00"],
+ //[60, 0, "RGB(200,200,200)", "18:00"],
+ [120, 1, "RGB(200,200,200)", "19:00"],
+ //[180, 0, "RGB(200,200,200)", "20:00"],
+ [240, 1, "RGB(200,200,200)", "21:00"],
+ //[300, 0, "RGB(200,200,200)", "22:00"],
+ [360, 1, "RGB(200,200,200)", "23:00"],
+ //[420, 0, "RGB(200,200,200)", "00:00"],
+ [480, 1, "RGB(200,200,200)", "01:00"],
+ //[540, 0, "RGB(200,200,200)", "02:00"],
+ [600, 1, "RGB(200,200,200)", "03:00"],
+ //[660, 1, "RGB(200,200,200)", "04:00"],
+ [706, 1, "RGB(200,200,200)", "09:00"],
+ //[766, 1, "RGB(200,200,200)", "10:00"],
+ [826, 1, "RGB(200,200,200)", "11:00"],
+ //[886, 1, "RGB(200,200,200)", "12:00"],
+ [946, 1, "RGB(200,200,200)", "13:00"],
+ //[1006, 1, "RGB(200,200,200)", "14:00"],
+ [1066, 1, "RGB(200,200,200)", "15:00"],
+ [1156, 1, "RGB(200,200,200)", "16:30"],
+ ],
+ Simple: //简洁模式
+ [
+ [0, 1, "RGB(200,200,200)", "17:00"],
+ //[60, 0, "RGB(200,200,200)", "18:00"],
+ //[120, 1, "RGB(200,200,200)", "19:00"],
+ //[180, 0, "RGB(200,200,200)", "20:00"],
+ [240, 1, "RGB(200,200,200)", "21:00"],
+ //[300, 0, "RGB(200,200,200)", "22:00"],
+ //[360, 1, "RGB(200,200,200)", "23:30"],
+ //[420, 0, "RGB(200,200,200)", "00:00"],
+ [480, 1, "RGB(200,200,200)", "01:00"],
+ //[540, 0, "RGB(200,200,200)", "02:00"],
+ //[600, 1, "RGB(200,200,200)", "03:00"],
+ //[660, 1, "RGB(200,200,200)", "04:00"],
+ [706, 1, "RGB(200,200,200)", "09:00"],
+ //[766, 1, "RGB(200,200,200)", "10:00"],
+ //[826, 1, "RGB(200,200,200)", "11:00"],
+ //[886, 1, "RGB(200,200,200)", "12:00"],
+ [946, 1, "RGB(200,200,200)", "13:00"],
+ //[1006, 1, "RGB(200,200,200)", "14:00"],
+ //[1066, 1, "RGB(200,200,200)", "15:00"],
+ [1156, 1, "RGB(200,200,200)", "16:30"],
+ ],
+ Min: //最小模式
+ [
+ [0, 1, "RGB(200,200,200)", "17:00"],
+ [706, 1, "RGB(200,200,200)", "09:00"],
+ [1156, 1, "RGB(200,200,200)", "16:30"],
+ ],
+
+ Count: 1157,
+ MiddleCount: 707,
+
+ GetData: function (width) {
+ if (width < 200) return this.Min;
+ else if (width < 450) return this.Simple;
+
+ return this.Full;
+ }
+ };
+
+ //港股指数期货
+ const FHK_MINUTE_X_COORDINATE =
+ {
+ Full: //完整模式
+ [
+ [0, 1, "RGB(200,200,200)", "17:15"],
+ //[45, 0, "RGB(200,200,200)", "18:00"],
+ [105, 1, "RGB(200,200,200)", "19:00"],
+ //[165, 0, "RGB(200,200,200)", "20:00"],
+ [225, 1, "RGB(200,200,200)", "21:00"],
+ //[285, 0, "RGB(200,200,200)", "22:00"],
+ [345, 1, "RGB(200,200,200)", "23:00"],
+ //[405, 0, "RGB(200,200,200)", "00:00"],
+ [466, 0, "RGB(200,200,200)", "09:15"],
+ //[511, 1, "RGB(200,200,200)", "10:00"],
+ [571, 1, "RGB(200,200,200)", "11:00"],
+ //[632, 1, "RGB(200,200,200)", "13:00"],
+ [692, 1, "RGB(200,200,200)", "14:00"],
+ //[752, 1, "RGB(200,200,200)", "15:00"],
+ [843, 1, "RGB(200,200,200)", "16:30"],
+ ],
+ Simple: //简洁模式
+ [
+ [0, 1, "RGB(200,200,200)", "17:15"],
+ //[45, 0, "RGB(200,200,200)", "18:00"],
+ //[105, 1, "RGB(200,200,200)", "19:00"],
+ //[165, 0, "RGB(200,200,200)", "20:00"],
+ [225, 1, "RGB(200,200,200)", "21:00"],
+ //[285, 0, "RGB(200,200,200)", "22:00"],
+ //[345, 1, "RGB(200,200,200)", "23:00"],
+ //[405, 0, "RGB(200,200,200)", "00:00"],
+ [466, 0, "RGB(200,200,200)", "09:15"],
+ //[511, 1, "RGB(200,200,200)", "10:00"],
+ //[571, 1, "RGB(200,200,200)", "11:00"],
+ [632, 1, "RGB(200,200,200)", "13:00"],
+ //[692, 1, "RGB(200,200,200)", "14:00"],
+ //[752, 1, "RGB(200,200,200)", "15:00"],
+ [843, 1, "RGB(200,200,200)", "16:30"],
+ ],
+ Min: //最小模式
+ [
+ [0, 1, "RGB(200,200,200)", "17:15"],
+ [466, 0, "RGB(200,200,200)", "09:15"],
+ [843, 1, "RGB(200,200,200)", "16:30"],
+ ],
+
+ Count: 843,
+ MiddleCount: 466,
+
+ GetData: function (width) {
+ if (width < 200) return this.Min;
+ else if (width < 450) return this.Simple;
+
+ return this.Full;
+ }
+ };
+
+ this.GetCoordinateData = function (symbol, width)
+ {
+ var data = null;
+ if (!symbol)
+ {
+ data = SHZE_MINUTE_X_COORDINATE; //默认沪深股票
+ }
+ else
+ {
+ var upperSymbol = symbol.toLocaleUpperCase(); //转成大写
+ if (MARKET_SUFFIX_NAME.IsSH(upperSymbol) || MARKET_SUFFIX_NAME.IsSZ(upperSymbol))
+ data = this.GetSHSZData(upperSymbol, width);
+ else if (MARKET_SUFFIX_NAME.IsSHO(upperSymbol))
+ data = this.GetSHOData(upperSymbol, width);
+ else if (MARKET_SUFFIX_NAME.IsHK(upperSymbol))
+ data = HK_MINUTE_X_COORDINATE;
+ else if (MARKET_SUFFIX_NAME.IsCFFEX(upperSymbol) || MARKET_SUFFIX_NAME.IsCZCE(upperSymbol) || MARKET_SUFFIX_NAME.IsDCE(upperSymbol) || MARKET_SUFFIX_NAME.IsSHFE(upperSymbol))
+ return this.GetChinatFuturesData(upperSymbol,width);
+ else if (MARKET_SUFFIX_NAME.IsUSA(upperSymbol))
+ data = this.GetUSAData(upperSymbol, width);
+ else if (MARKET_SUFFIX_NAME.IsFTSE(upperSymbol, width))
+ data = this.GetFTSEData(upperSymbol, width);
+ else if (MARKET_SUFFIX_NAME.IsFHK(upperSymbol, width))
+ data = this.GetFHKData(upperSymbol, width);
+ else if (MARKET_SUFFIX_NAME.IsET(upperSymbol))
+ data = this.GetETData(upperSymbol, width);
+ else if (MARKET_SUFFIX_NAME.IsNYMEX(upperSymbol, width))
+ return data = this.GetNYMEXData(upperSymbol, width);
+ else if (MARKET_SUFFIX_NAME.IsCOMEX(upperSymbol,width))
+ return data=this.GetCOMEXData(upperSymbol,width);
+ else if (MARKET_SUFFIX_NAME.IsNYBOT(upperSymbol,width))
+ return data=this.GetNYBOTData(upperSymbol,width);
+ else if (MARKET_SUFFIX_NAME.IsCBOT(upperSymbol,width))
+ return data=this.GetCBOTData(upperSymbol,width);
+ else if (MARKET_SUFFIX_NAME.IsLME(upperSymbol,width))
+ return data=this.GetLMEData(upperSymbol,width);
+ else if ((MARKET_SUFFIX_NAME.IsBIT(upperSymbol,width)))
+ data=this.GetBITData(upperSymbol,width);
+ }
+
+ //console.log('[MiuteCoordinateData]', width);
+ var result = { Count: data.Count, MiddleCount: data.MiddleCount, Data: data.GetData(width) };
+ return result;
+ }
+
+ this.GetSHSZData = function (upperSymbol, width)
+ {
+ var result = SHZE_MINUTE_X_COORDINATE;
+ return result;
+ }
+
+ this.GetFuturesData = function (upperSymbol,width,timeData)
+ {
+ var splitData = timeData.GetSplitData(upperSymbol);
+ if (!splitData) return null;
+ var stringData = g_MinuteTimeStringData.GetFutures(splitData);
+ if (!stringData) return null;
+ var result = { Count: stringData.length };
+ var coordinate=null;
+ var minWidth=200, simpleWidth=480;
+ /*
+ if (splitData.Name =='21:00-1:00,9:00-10:15,10:30-11:30,13:30-15:00')
+ {
+ minWidth=250;
+ simpleWidth=500;
+ }
+ */
+
+ if (width < minWidth) coordinate = splitData.Coordinate.Min;
+ else if (width < simpleWidth) coordinate = splitData.Coordinate.Simple;
+ else coordinate = splitData.Coordinate.Full;
+
+ var data=[];
+ for(var i=0;i430 && time<730) return 1;
+
+ return 2;
+ }
+}
+
+function COMEXTimeData()
+{
+ this.newMethod=NYMEXTimeData; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.FUTURES_LIST=
+ [
+ { Symbol:"GC", Decimal:1, Time:0 }, //COMEX黄金
+ { Symbol:"QO", Decimal:2, Time:0 }, //迷你黄金
+ { Symbol:"MG", Decimal:1, Time:0 }, //微型黄金
+ { Symbol:"QI", Decimal:4, Time:0 }, //迷你白银
+ { Symbol:"SI", Decimal:3, Time:0 }, //COMEX白银
+ { Symbol:"QI", Decimal:4, Time:0 }, //迷你白银
+ { Symbol:"HG", Decimal:4, Time:0 } //COMEX铜
+ ]
+
+ this.MarketSuffix=".COMEX";
+}
+
+function NYBOTTimeData()
+{
+ this.newMethod=NYMEXTimeData; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ //美国标准时间
+ this.TIME_SPLIT=
+ [
+ {
+ Name:'9:00-2:20',
+ Data:
+ [
+ //9:00-2:20
+ { Start: 900, End: 2359 },
+ { Start: 0, End: 220 },
+ ],
+ Coordinate:
+ {
+ Full://完整模式
+ [
+ { Value: 900, Text: '9:00' },
+ { Value: 1100, Text: '11:00' },
+ { Value: 1300, Text: '13:00' },
+ { Value: 1500, Text: '15:00' },
+ { Value: 1700, Text: '17:00' },
+ { Value: 1900, Text: '19:00' },
+ { Value: 2100, Text: '21:00' },
+ { Value: 2300, Text: '23:00' },
+ { Value: 100, Text: '1:00' }
+ ],
+ Simple: //简洁模式
+ [
+ { Value: 900, Text: '9:00' },
+ //{ Value: 1100, Text: '11:00' },
+ { Value: 1300, Text: '13:00' },
+ //{ Value: 1500, Text: '15:00' },
+ { Value: 1700, Text: '17:00' },
+ //{ Value: 1900, Text: '19:00' },
+ { Value: 2100, Text: '21:00' },
+ //{ Value: 2300, Text: '23:00' },
+ { Value: 100, Text: '1:00' }
+ ],
+ Min: //最小模式
+ [
+ { Value: 900, Text: '9:00' },
+ { Value: 1700, Text: '17:00' },
+ { Value: 100, Text: '1:00' }
+ ]
+ }
+ },
+ {
+ Name:'15:30-1:00',
+ Data:
+ [
+ //9:00-2:20
+ { Start: 1530, End: 2359 },
+ { Start: 0, End: 100 },
+ ],
+ Coordinate:
+ {
+ Full://完整模式
+ [
+ { Value: 1600, Text: '16:00' },
+ { Value: 1700, Text: '17:00' },
+ { Value: 1800, Text: '18:00' },
+ { Value: 1900, Text: '19:00' },
+ { Value: 2000, Text: '20:00' },
+ { Value: 2100, Text: '21:00' },
+ { Value: 2200, Text: '22:00' },
+ { Value: 2300, Text: '23:00' },
+ { Value: 0, Text: '0:00' },
+ { Value: 100, Text: '1:00' }
+ ],
+ Simple: //简洁模式
+ [
+ { Value: 1600, Text: '16:00' },
+ //{ Value: 1600, Text: '17:00' },
+ { Value: 1800, Text: '18:00' },
+ //{ Value: 1900, Text: '19:00' },
+ { Value: 2000, Text: '20:00' },
+ //{ Value: 2100, Text: '21:00' },
+ { Value: 2200, Text: '22:00' },
+ //{ Value: 2300, Text: '23:00' },
+ { Value: 0, Text: '0:00' },
+ //{ Value: 100, Text: '1:00' }
+ ],
+ Min: //最小模式
+ [
+ { Value: 1600, Text: '16:00' },
+ { Value: 2100, Text: '21:00' },
+ { Value: 100, Text: '1:00' }
+ ]
+ }
+ }
+ ]
+
+ //美国夏时令
+ this.TIME_SPLIT2=
+ [
+ {
+ Name:'10:00-3:20',
+ Data:
+ [
+ //9:00-2:20
+ { Start: 1000, End: 2359 },
+ { Start: 0, End: 320 },
+ ],
+ Coordinate:
+ {
+ Full://完整模式
+ [
+ { Value: 1000, Text: '10:00' },
+ { Value: 1200, Text: '12:00' },
+ { Value: 1400, Text: '14:00' },
+ { Value: 1600, Text: '16:00' },
+ { Value: 1800, Text: '18:00' },
+ { Value: 2000, Text: '20:00' },
+ { Value: 2200, Text: '22:00' },
+ { Value: 0, Text: '0:00' },
+ { Value: 200, Text: '2:00' }
+ ],
+ Simple: //简洁模式
+ [
+ { Value: 1000, Text: '10:00' },
+ //{ Value: 1200, Text: '12:00' },
+ { Value: 1400, Text: '14:00' },
+ //{ Value: 1600, Text: '16:00' },
+ { Value: 1800, Text: '18:00' },
+ //{ Value: 2000, Text: '20:00' },
+ { Value: 2200, Text: '22:00' },
+ //{ Value: 0, Text: '0:00' },
+ { Value: 200, Text: '2:00' }
+ ],
+ Min: //最小模式
+ [
+ { Value: 1000, Text: '10:00' },
+ { Value: 1800, Text: '18:00' },
+ { Value: 200, Text: '2:00' }
+ ]
+ }
+ },
+ {
+ Name:'16:30-2:00',
+ Data:
+ [
+ { Start: 1630, End: 2359 },
+ { Start: 0, End: 200 },
+ ],
+ Coordinate:
+ {
+ Full://完整模式
+ [
+ { Value: 1700, Text: '17:00' },
+ { Value: 1800, Text: '18:00' },
+ { Value: 1900, Text: '19:00' },
+ { Value: 2000, Text: '20:00' },
+ { Value: 2100, Text: '21:00' },
+ { Value: 2200, Text: '22:00' },
+ { Value: 2300, Text: '23:00' },
+ { Value: 0, Text: '0:00' },
+ { Value: 100, Text: '1:00' },
+ { Value: 200, Text: '2:00' }
+ ],
+ Simple: //简洁模式
+ [
+ { Value: 1700, Text: '17:00' },
+ //{ Value: 1800, Text: '18:00' },
+ { Value: 1900, Text: '19:00' },
+ //{ Value: 2000, Text: '20:00' },
+ { Value: 2100, Text: '21:00' },
+ //{ Value: 2200, Text: '22:00' },
+ { Value: 2300, Text: '23:00' },
+ //{ Value: 0, Text: '0:00' },
+ { Value: 100, Text: '1:00' }
+ //{ Value: 200, Text: '2:00' }
+ ],
+ Min: //最小模式
+ [
+ { Value: 1700, Text: '17:00' },
+ { Value: 2100, Text: '21:00' },
+ { Value: 200, Text: '2:00' }
+ ]
+ }
+ }
+ ]
+
+ this.FUTURES_LIST=
+ [
+ { Symbol:"SB", Decimal:2, Time:1 }, //11号白糖
+ { Symbol:"CT", Decimal:2, Time:0 }, //棉花
+ //{ Symbol:"KC", Decimal:2, Time:0 }, //咖啡
+ //{ Symbol:"DX", Decimal:2, Time:0 }, //美元指数
+ //{ Symbol:"CC", Decimal:2, Time:0 } //可可
+ ]
+
+ this.MarketSuffix=".NYBOT";
+
+ this.GetMarketStatus=function(upperSymbol) // 0=闭市 1=盘前 2=盘中 3=盘后
+ {
+ var usaDate=GetLocalTime(-4); //需要转成美国时间的 周6 周日
+ var day = usaDate.getDay();
+ var time = usaDate.getHours() * 100 + usaDate.getMinutes();
+ if(day == 6 || day== 0) return 0; //周末
+
+ var find=this.GetFuturesInfo(upperSymbol);
+ if (!find) return 2;
+
+ if (find.Symbol=="SB") //Sugar No. 11 Futures 03:30 - 13:00
+ {
+ if (time>300 && time<1400) return 2;
+ }
+ else if (find.Symbol=="CT") //美棉 21:00-14:20
+ {
+ if( (time>=0 && time<=1500 ) || (time>=2000 && time<=2359) ) return 2;
+ return 1;
+ }
+
+ return 0;
+ }
+}
+
+//芝商所
+function CBOTTimeData()
+{
+ this.newMethod=NYMEXTimeData; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ //夏令时间
+ this.TIME_SPLIT=
+ [
+ {
+ Name:'8:00-2:20',
+ Data:
+ [
+ //6:00 - 5:00
+ { Start: 800, End: 2359 },
+ { Start: 0, End: 220 },
+ ],
+ Coordinate:
+ {
+ Full://完整模式
+ [
+ { Value: 800, Text: '8:00' },
+ { Value: 1000, Text: '10:00' },
+ { Value: 1200, Text: '12:00' },
+ { Value: 1400, Text: '14:00' },
+ { Value: 1600, Text: '16:00' },
+ { Value: 1800, Text: '18:00' },
+ { Value: 2000, Text: '20:00' },
+ { Value: 2200, Text: '22:00' },
+ { Value: 0, Text: '0:00' },
+ { Value: 200, Text: '2:00' }
+ ],
+ Simple: //简洁模式
+ [
+ { Value: 800, Text: '8:00' },
+ //{ Value: 1000, Text: '10:00' },
+ { Value: 1200, Text: '12:00' },
+ //{ Value: 1400, Text: '14:00' },
+ { Value: 1600, Text: '16:00' },
+ //{ Value: 1800, Text: '18:00' },
+ { Value: 2000, Text: '20:00' },
+ //{ Value: 2200, Text: '22:00' },
+ { Value: 0, Text: '0:00' }
+ //{ Value: 200, Text: '2:00' }
+ ],
+ Min: //最小模式
+ [
+ { Value: 800, Text: '8:00' },
+ { Value: 1800, Text: '18:00' },
+ { Value: 200, Text: '2:00' }
+ ]
+ }
+ },
+ {
+ Name:'8:00-2:45',
+ Data:
+ [
+ //6:00 - 5:00
+ { Start: 800, End: 2359 },
+ { Start: 0, End: 245 },
+ ],
+ Coordinate:
+ {
+ Full://完整模式
+ [
+ { Value: 800, Text: '8:00' },
+ { Value: 1000, Text: '10:00' },
+ { Value: 1200, Text: '12:00' },
+ { Value: 1400, Text: '14:00' },
+ { Value: 1600, Text: '16:00' },
+ { Value: 1800, Text: '18:00' },
+ { Value: 2000, Text: '20:00' },
+ { Value: 2200, Text: '22:00' },
+ { Value: 0, Text: '0:00' },
+ { Value: 200, Text: '2:00' }
+ ],
+ Simple: //简洁模式
+ [
+ { Value: 800, Text: '8:00' },
+ //{ Value: 1000, Text: '10:00' },
+ { Value: 1200, Text: '12:00' },
+ //{ Value: 1400, Text: '14:00' },
+ { Value: 1600, Text: '16:00' },
+ //{ Value: 1800, Text: '18:00' },
+ { Value: 2000, Text: '20:00' },
+ //{ Value: 2200, Text: '22:00' },
+ { Value: 0, Text: '0:00' }
+ //{ Value: 200, Text: '2:00' }
+ ],
+ Min: //最小模式
+ [
+ { Value: 800, Text: '8:00' },
+ { Value: 1800, Text: '18:00' },
+ { Value: 200, Text: '2:00' }
+ ]
+ }
+ },
+ {
+ Name:'6:00-5:00',
+ Data:
+ [
+ //6:00 - 5:00
+ { Start: 600, End: 2359 },
+ { Start: 0, End: 500 },
+ ],
+ Coordinate:
+ {
+ Full://完整模式
+ [
+ { Value: 600, Text: '6:00' },
+ { Value: 800, Text: '8:00' },
+ { Value: 1000, Text: '10:00' },
+ { Value: 1200, Text: '12:00' },
+ { Value: 1400, Text: '14:00' },
+ { Value: 1600, Text: '16:00' },
+ { Value: 1800, Text: '18:00' },
+ { Value: 2000, Text: '20:00' },
+ { Value: 2200, Text: '22:00' },
+ { Value: 0, Text: '0:00' },
+ { Value: 200, Text: '2:00' },
+ { Value: 400, Text: '4:00' },
+ ],
+ Simple: //简洁模式
+ [
+ { Value: 600, Text: '6:00' },
+ //{ Value: 800, Text: '8:00' },
+ { Value: 1000, Text: '10:00' },
+ //{ Value: 1200, Text: '12:00' },
+ { Value: 1400, Text: '14:00' },
+ //{ Value: 1600, Text: '16:00' },
+ { Value: 1800, Text: '18:00' },
+ //{ Value: 2000, Text: '20:00' },
+ { Value: 2200, Text: '22:00' },
+ //{ Value: 0, Text: '0:00' },
+ { Value: 200, Text: '2:00' }
+ //{ Value: 400, Text: '4:00' },
+ ],
+ Min: //最小模式
+ [
+ { Value: 600, Text: '6:00' },
+ { Value: 1800, Text: '18:00' },
+ { Value: 500, Text: '5:00' }
+ ]
+ }
+ }
+ ]
+
+ //标准时间
+ this.TIME_SPLIT2=
+ [
+ {
+ Name:'9:00-3:20',
+ Data:
+ [
+ { Start: 900, End: 2359 },
+ { Start: 0, End: 320 },
+ ],
+ Coordinate:
+ {
+ Full://完整模式
+ [
+ { Value: 900, Text: '9:00' },
+ { Value: 1100, Text: '11:00' },
+ { Value: 1300, Text: '13:00' },
+ { Value: 1500, Text: '15:00' },
+ { Value: 1700, Text: '17:00' },
+ { Value: 1900, Text: '19:00' },
+ { Value: 2100, Text: '21:00' },
+ { Value: 2300, Text: '23:00' },
+ { Value: 1, Text: '1:00' },
+ { Value: 300, Text: '3:00' }
+ ],
+ Simple: //简洁模式
+ [
+ { Value: 900, Text: '9:00' },
+ //{ Value: 1100, Text: '11:00' },
+ { Value: 1300, Text: '13:00' },
+ //{ Value: 1500, Text: '15:00' },
+ { Value: 1700, Text: '17:00' },
+ //{ Value: 1900, Text: '19:00' },
+ { Value: 2100, Text: '21:00' },
+ //{ Value: 2300, Text: '23:00' },
+ { Value: 1, Text: '1:00' }
+ //{ Value: 300, Text: '3:00' }
+ ],
+ Min: //最小模式
+ [
+ { Value: 900, Text: '9:00' },
+ { Value: 1900, Text: '19:00' },
+ { Value: 300, Text: '3:00' }
+ ]
+ }
+ },
+ {
+ Name:'9:00-3:45',
+ Data:
+ [
+ { Start: 900, End: 2359 },
+ { Start: 0, End: 345 },
+ ],
+ Coordinate:
+ {
+ Full://完整模式
+ [
+ { Value: 900, Text: '9:00' },
+ { Value: 1100, Text: '11:00' },
+ { Value: 1300, Text: '13:00' },
+ { Value: 1500, Text: '15:00' },
+ { Value: 1700, Text: '17:00' },
+ { Value: 1900, Text: '19:00' },
+ { Value: 2100, Text: '21:00' },
+ { Value: 2300, Text: '23:00' },
+ { Value: 1, Text: '1:00' },
+ { Value: 300, Text: '3:00' }
+ ],
+ Simple: //简洁模式
+ [
+ { Value: 900, Text: '9:00' },
+ //{ Value: 1100, Text: '11:00' },
+ { Value: 1300, Text: '13:00' },
+ //{ Value: 1500, Text: '15:00' },
+ { Value: 1700, Text: '17:00' },
+ //{ Value: 1900, Text: '19:00' },
+ { Value: 2100, Text: '21:00' },
+ //{ Value: 2300, Text: '23:00' },
+ { Value: 1, Text: '1:00' }
+ //{ Value: 300, Text: '3:00' }
+ ],
+ Min: //最小模式
+ [
+ { Value: 900, Text: '9:00' },
+ { Value: 1900, Text: '19:00' },
+ { Value: 300, Text: '3:00' }
+ ]
+ }
+ },
+ {
+ Name:'7:00-6:00',
+ Data:
+ [
+ { Start: 700, End: 2359 },
+ { Start: 0, End: 600 },
+ ],
+ Coordinate:
+ {
+ Full://完整模式
+ [
+ { Value: 700, Text: '7:00' },
+ { Value: 900, Text: '9:00' },
+ { Value: 1100, Text: '11:00' },
+ { Value: 1300, Text: '13:00' },
+ { Value: 1500, Text: '15:00' },
+ { Value: 1700, Text: '17:00' },
+ { Value: 1900, Text: '19:00' },
+ { Value: 2100, Text: '21:00' },
+ { Value: 2300, Text: '23:00' },
+ { Value: 1, Text: '1:00' },
+ { Value: 300, Text: '3:00' },
+ { Value: 500, Text: '5:00' }
+ ],
+ Simple: //简洁模式
+ [
+ { Value: 700, Text: '7:00' },
+ //{ Value: 900, Text: '9:00' },
+ { Value: 1100, Text: '11:00' },
+ //{ Value: 1300, Text: '13:00' },
+ { Value: 1500, Text: '15:00' },
+ //{ Value: 1700, Text: '17:00' },
+ { Value: 1900, Text: '19:00' },
+ //{ Value: 2100, Text: '21:00' },
+ { Value: 2300, Text: '23:00' },
+ //{ Value: 1, Text: '1:00' },
+ { Value: 300, Text: '3:00' }
+ //{ Value: 500, Text: '5:00' }
+ ],
+ Min: //最小模式
+ [
+ { Value: 700, Text: '7:00' },
+ { Value: 1800, Text: '18:00' },
+ { Value: 500, Text: '5:00' }
+ ]
+ }
+ }
+ ]
+
+ this.FUTURES_LIST=
+ [
+ { Symbol:"ZC", Decimal:2, Time:0 }, //玉米
+ { Symbol:"XC", Decimal:2, Time:1 }, //迷你玉米
+ { Symbol:"ZS", Decimal:2, Time:0 }, //大豆
+ { Symbol:"XK", Decimal:2, Time:1 }, //迷你大豆
+ { Symbol:"ZL", Decimal:2, Time:0 }, //豆油
+ { Symbol:"ZR", Decimal:2, Time:0 }, //稻谷
+ { Symbol:"ZO", Decimal:2, Time:0 }, //燕麦
+ { Symbol:"ZW", Decimal:2, Time:0 }, //小麦
+ { Symbol:"XW", Decimal:2, Time:1 }, //迷你小麦
+ { Symbol:"ZM", Decimal:1, Time:0 }, //豆粕
+
+ { Symbol:"EH", Decimal:3, Time:2 }, //乙醇
+
+ { Symbol:"YM", Decimal:0, Time:2 }, //小型道指
+ { Symbol:"ES", Decimal:2, Time:2 }, //小型标普
+ { Symbol:"NQ", Decimal:2, Time:2 }, //小型纳指
+
+ { Symbol:"TY", Decimal:4, Time:2 }, //10年美国债
+ { Symbol:"TU", Decimal:4, Time:2 }, //2年美国债
+ { Symbol:"FV", Decimal:4, Time:2 }, //5年美国债
+ { Symbol:"US", Decimal:4, Time:2 }, //30年美国债
+ { Symbol:"UL", Decimal:4, Time:2 }, //超国债
+ ]
+
+ this.MarketSuffix=".CBOT";
+}
+
+function LMETimeData()
+{
+ this.newMethod=NYMEXTimeData; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ //标准时间
+ this.TIME_SPLIT=
+ [
+ {
+ Name:'LME 9:00-3:00',
+ Data:
+ [
+ { Start: 900, End: 2359 },
+ { Start: 0, End: 300 },
+ ],
+ Coordinate:
+ {
+ Full://完整模式
+ [
+ { Value: 900, Text: '9:00' },
+ { Value: 1100, Text: '11:00' },
+ { Value: 1300, Text: '13:00' },
+ { Value: 1500, Text: '15:00' },
+ { Value: 1700, Text: '17:00' },
+ { Value: 1900, Text: '19:00' },
+ { Value: 2100, Text: '21:00' },
+ { Value: 2300, Text: '23:00' },
+ { Value: 100, Text: '1:00' },
+ { Value: 300, Text: '3:00' }
+ ],
+ Simple: //简洁模式
+ [
+ { Value: 900, Text: '9:00' },
+ //{ Value: 1100, Text: '11:00' },
+ { Value: 1300, Text: '13:00' },
+ //{ Value: 1500, Text: '15:00' },
+ { Value: 1700, Text: '17:00' },
+ //{ Value: 1900, Text: '19:00' },
+ { Value: 2100, Text: '21:00' },
+ //{ Value: 2300, Text: '23:00' },
+ { Value: 100, Text: '1:00' }
+ // { Value: 300, Text: '3:00' }
+ ],
+ Min: //最小模式
+ [
+ { Value: 900, Text: '9:00' },
+ { Value: 1800, Text: '18:00' },
+ { Value: 300, Text: '3:00' }
+ ]
+ }
+ }
+ ]
+
+ //夏令
+ this.TIME_SPLIT=
+ [
+ {
+ Name:'LME 8:00-2:00',
+ Data:
+ [
+ { Start: 800, End: 2359 },
+ { Start: 0, End: 200 },
+ ],
+ Coordinate:
+ {
+ Full://完整模式
+ [
+ { Value: 800, Text: '8:00' },
+ { Value: 1000, Text: '10:00' },
+ { Value: 1200, Text: '12:00' },
+ { Value: 1400, Text: '14:00' },
+ { Value: 1600, Text: '16:00' },
+ { Value: 1800, Text: '18:00' },
+ { Value: 2000, Text: '20:00' },
+ { Value: 2200, Text: '22:00' },
+ { Value: 0, Text: '0:00' },
+ { Value: 200, Text: '2:00' }
+ ],
+ Simple: //简洁模式
+ [
+ { Value: 800, Text: '8:00' },
+ //{ Value: 1000, Text: '10:00' },
+ { Value: 1200, Text: '12:00' },
+ //{ Value: 1400, Text: '14:00' },
+ { Value: 1600, Text: '16:00' },
+ //{ Value: 1800, Text: '18:00' },
+ { Value: 2000, Text: '20:00' },
+ //{ Value: 2200, Text: '22:00' },
+ { Value: 0, Text: '0:00' }
+ //{ Value: 200, Text: '2:00' }
+ ],
+ Min: //最小模式
+ [
+ { Value: 800, Text: '8:00' },
+ { Value: 1800, Text: '18:00' },
+ { Value: 200, Text: '2:00' }
+ ]
+ }
+ }
+ ]
+
+ this.FUTURES_LIST=
+ [
+ { Symbol:"SND", Decimal:0, Time:0 }, //综合锡03
+ { Symbol:"AHD", Decimal:2, Time:0 }, //综合铝03
+ { Symbol:"PBD", Decimal:2, Time:0 }, //综合铅03
+ { Symbol:"ZSD", Decimal:2, Time:0 }, //综合锌03
+ { Symbol:"CAD", Decimal:2, Time:0 }, //综合铜03
+ { Symbol:"NID", Decimal:0, Time:0 }, //综合镍03
+ ]
+
+ this.MarketSuffix=".LME";
+}
+
+var g_MinuteTimeStringData = new MinuteTimeStringData();
+var g_MinuteCoordinateData = new MinuteCoordinateData();
+var g_FuturesTimeData = new FuturesTimeData();
+var g_NYMEXTimeData = new NYMEXTimeData();
+var g_COMEXTimeData=new COMEXTimeData();
+var g_NYBOTTimeData=new NYBOTTimeData();
+var g_CBOTTimeData=new CBOTTimeData();
+var g_LMETimeData=new LMETimeData();
+
+
+function GetfloatPrecision(symbol) //获取小数位数
+{
+ var defaultfloatPrecision = 2; //默认2位
+ if (!symbol) return defaultfloatPrecision;
+ var upperSymbol = symbol.toUpperCase();
+
+ //全部由外部控制
+ if (typeof(MARKET_SUFFIX_NAME.GetCustomDecimal)=='function') return MARKET_SUFFIX_NAME.GetCustomDecimal(upperSymbol);
+
+ if (MARKET_SUFFIX_NAME.IsSHSZFund(upperSymbol)) defaultfloatPrecision = 3; //基金3位小数
+ else if (MARKET_SUFFIX_NAME.IsSHO(upperSymbol)) defaultfloatPrecision = MARKET_SUFFIX_NAME.GetSHODecimal(upperSymbol);
+ else if (MARKET_SUFFIX_NAME.IsChinaFutures(upperSymbol)) defaultfloatPrecision = g_FuturesTimeData.GetDecimal(upperSymbol); //期货小数位数读配置
+ else if (MARKET_SUFFIX_NAME.IsFHK(upperSymbol)) defaultfloatPrecision = MARKET_SUFFIX_NAME.GetFHKDecimal(upperSymbol);
+ else if (MARKET_SUFFIX_NAME.IsFTSE(upperSymbol)) defaultfloatPrecision = MARKET_SUFFIX_NAME.GetFTSEDecimal(upperSymbol);
+ else if (MARKET_SUFFIX_NAME.IsBIT(upperSymbol)) defaultfloatPrecision = MARKET_SUFFIX_NAME.GetBITDecimal(upperSymbol);
+ else if (MARKET_SUFFIX_NAME.IsET(upperSymbol)) defaultfloatPrecision = MARKET_SUFFIX_NAME.GetETDecimal(upperSymbol);
+ else if (MARKET_SUFFIX_NAME.IsNYMEX(upperSymbol)) defaultfloatPrecision=g_NYMEXTimeData.GetDecimal(upperSymbol);
+ else if (MARKET_SUFFIX_NAME.IsCOMEX(upperSymbol)) defaultfloatPrecision=g_COMEXTimeData.GetDecimal(upperSymbol);
+ else if (MARKET_SUFFIX_NAME.IsNYBOT(upperSymbol)) defaultfloatPrecision=g_NYBOTTimeData.GetDecimal(upperSymbol);
+ else if (MARKET_SUFFIX_NAME.IsCBOT(upperSymbol)) defaultfloatPrecision=g_CBOTTimeData.GetDecimal(upperSymbol);
+ else defaultfloatPrecision=MARKET_SUFFIX_NAME.GetDefaultDecimal(upperSymbol);
+
+ return defaultfloatPrecision;
+}
+
+//导出统一使用JSCommon命名空间名
+module.exports =
+{
+ JSCommonCoordinateData:
+ {
+ MinuteCoordinateData: g_MinuteCoordinateData,
+ MinuteTimeStringData: g_MinuteTimeStringData,
+ MARKET_SUFFIX_NAME: MARKET_SUFFIX_NAME,
+ GetfloatPrecision: GetfloatPrecision
+ },
+
+ JSCommonCoordinateData_MARKET_SUFFIX_NAME: MARKET_SUFFIX_NAME,
+ JSCommonCoordinateData_Global_FuturesTimeData: g_FuturesTimeData,
+ JSCommonCoordinateData_Global_NYMEXTimeData: g_NYMEXTimeData,
+ JSCommonCoordinateData_Global_COMEXTimeData: g_COMEXTimeData,
+ JSCommonCoordinateData_Global_NYBOTTimeData: g_NYBOTTimeData,
+ JSCommonCoordinateData_Global_LMETimeData: g_LMETimeData,
+ JSCommonCoordinateData_Global_CBOTTimeData: g_CBOTTimeData,
+};
\ No newline at end of file
diff --git a/uni_modules/jones-hqchart2/js_sdk/umychart.data.wechat.js b/uni_modules/jones-hqchart2/js_sdk/umychart.data.wechat.js
new file mode 100644
index 0000000..e56670d
--- /dev/null
+++ b/uni_modules/jones-hqchart2/js_sdk/umychart.data.wechat.js
@@ -0,0 +1,1796 @@
+/*
+ copyright (c) 2018 jones
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ 开源项目 https://github.com/jones2000/HQChart
+
+ jones_2000@163.com
+
+ 行情数据结构 及计算方法
+*/
+
+import
+{
+ JSCommonCoordinateData_MARKET_SUFFIX_NAME as MARKET_SUFFIX_NAME
+} from "./umychart.coordinatedata.wechat.js";
+
+function Guid()
+{
+ function S4()
+ {
+ return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
+ }
+
+ return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
+}
+
+//历史K线数据
+function HistoryData()
+{
+ this.Date;
+ this.YClose;
+ this.Open;
+ this.Close;
+ this.High;
+ this.Low;
+ this.Vol;
+ this.Amount;
+ this.Time; //分钟 HHMM / 秒HHMMSS
+ this.FlowCapital = 0; //流通股本
+ this.Position = null; //持仓量
+
+ //指数才有的数据
+ this.Stop; //停牌家数
+ this.Up; //上涨
+ this.Down; //下跌
+ this.Unchanged; //平盘
+}
+
+//数据复制
+HistoryData.Copy=function(data)
+{
+ var newData=new HistoryData();
+ newData.Date=data.Date;
+ newData.YClose=data.YClose;
+ newData.Open=data.Open;
+ newData.Close=data.Close;
+ newData.High=data.High;
+ newData.Low=data.Low;
+ newData.Vol=data.Vol;
+ newData.Amount=data.Amount;
+ newData.Time=data.Time;
+ newData.FlowCapital = data.FlowCapital;
+ newData.Position = data.Position;
+
+ //指数才有的数据
+ newData.Stop = data.Stop;
+ newData.Up = data.Up;
+ newData.Down = data.Down;
+ newData.Unchanged = data.Unchanged;
+
+ return newData;
+}
+
+//把数据 src 复制到 dest中
+HistoryData.CopyTo = function (dest, src)
+{
+ dest.Date = src.Date;
+ dest.YClose = src.YClose;
+ dest.Open = src.Open;
+ dest.Close = src.Close;
+ dest.High = src.High;
+ dest.Low = src.Low;
+ dest.Vol = src.Vol;
+ dest.Amount = src.Amount;
+ dest.Time = src.Time;
+ dest.FlowCapital = src.FlowCapital;
+
+ dest.Stop = src.Stop;
+ dest.Up = src.Up;
+ dest.Down = src.Down;
+ dest.Unchanged = src.Unchanged;
+}
+
+//数据复权拷贝
+HistoryData.CopyRight=function(data,seed)
+{
+ var newData=new HistoryData();
+ newData.Date=data.Date;
+ newData.YClose=data.YClose*seed;
+ newData.Open=data.Open*seed;
+ newData.Close=data.Close*seed;
+ newData.High=data.High*seed;
+ newData.Low=data.Low*seed;
+
+ newData.Vol=data.Vol;
+ newData.Amount=data.Amount;
+
+ newData.FlowCapital = data.FlowCapital;
+ newData.Position = data.Position;
+
+ return newData;
+}
+
+//分钟数据
+function MinuteData()
+{
+ this.Close;
+ this.Open;
+ this.High;
+ this.Low;
+ this.Vol;
+ this.Amount;
+ this.DateTime;
+ this.Increase;
+ this.Risefall;
+ this.AvPrice;
+ this.Date;
+ this.Time;
+ this.Position = null; //持仓量
+}
+
+//单指标数据
+function SingleData()
+{
+ this.Date; //日期
+ this.Value; //数据
+}
+
+
+function DataPlus() { }; //外部数据计算方法接口
+DataPlus.GetMinutePeriodData = null;
+/*
+DataPlus.GetMinutePeriodData=function(period,data,self)
+{
+
+}
+*/
+
+//////////////////////////////////////////////////////////////////////
+// 数据集合
+function ChartData()
+{
+ this.Data=new Array();
+ this.DataOffset=0; //数据偏移
+ this.Period=0; //周期 0 日线 1 周线 2 月线 3年线
+ this.Right=0; //复权 0 不复权 1 前复权 2 后复权
+ this.Symbol; //股票代码
+
+ this.Data2=new Array(); //第1组数据 走势图:历史分钟数据
+
+ this.GetCloseMA=function(dayCount)
+ {
+ var result=new Array();
+ for (var i = 0, len = this.Data.length; i < len; i++)
+ {
+ if (i < dayCount)
+ {
+ result[i]=null;
+ continue;
+ }
+
+ var sum = 0;
+ for (var j = 0; j < dayCount; j++)
+ {
+ sum += this.Data[i - j].Close;
+ }
+ result[i]=sum / dayCount;
+ }
+ return result;
+ }
+
+ this.GetVolMA=function(dayCount)
+ {
+ var result=new Array();
+ for (var i = 0, len = this.Data.length; i < len; i++)
+ {
+ if (i < dayCount)
+ {
+ result[i]=null;
+ continue;
+ }
+
+ var sum = 0;
+ for (var j = 0; j < dayCount; j++)
+ {
+ sum += this.Data[i - j].Vol;
+ }
+ result[i]=sum / dayCount;
+ }
+ return result;
+ }
+
+ this.GetAmountMA=function(dayCount)
+ {
+ var result=new Array();
+ for (var i = 0, len = this.Data.length; i < len; i++)
+ {
+ if (i < dayCount)
+ {
+ result[i]=null;
+ continue;
+ }
+
+ var sum = 0;
+ for (var j = 0; j < dayCount; j++)
+ {
+ sum += this.Data[i - j].Amount;
+ }
+ result[i]=sum / dayCount;
+ }
+ return result;
+ }
+
+ //获取收盘价
+ this.GetClose=function()
+ {
+ var result=new Array();
+ for(var i in this.Data)
+ {
+ result[i]=this.Data[i].Close;
+ }
+
+ return result;
+ }
+
+ this.GetYClose=function()
+ {
+ var result=new Array();
+ for(var i in this.Data)
+ {
+ result[i]=this.Data[i].YClose;
+ }
+
+ return result;
+ }
+
+ this.GetHigh=function()
+ {
+ var result=new Array();
+ for(var i in this.Data)
+ {
+ result[i]=this.Data[i].High;
+ }
+
+ return result;
+ }
+
+ this.GetLow=function()
+ {
+ var result=new Array();
+ for(var i in this.Data)
+ {
+ result[i]=this.Data[i].Low;
+ }
+
+ return result;
+ }
+
+ this.GetOpen=function()
+ {
+ var result=new Array();
+ for(var i in this.Data)
+ {
+ result[i]=this.Data[i].Open;
+ }
+
+ return result;
+ }
+
+ this.GetVol=function()
+ {
+ var result=new Array();
+ for(var i in this.Data)
+ {
+ result[i]=this.Data[i].Vol;
+ }
+
+ return result;
+ }
+
+ this.GetAmount=function()
+ {
+ var result=new Array();
+ for(var i in this.Data)
+ {
+ result[i]=this.Data[i].Amount;
+ }
+
+ return result;
+ }
+
+ this.GetPosition = function ()
+ {
+ var result = new Array();
+ for (var i in this.Data)
+ {
+ result[i] = this.Data[i].Position;
+ }
+
+ return result;
+ }
+
+ this.GetDate = function ()
+ {
+ var result = [];
+ for (var i in this.Data)
+ {
+ result[i] = this.Data[i].Date;
+ }
+
+ return result;
+ }
+
+ this.GetTime = function ()
+ {
+ var result = [];
+ for (var i in this.Data)
+ {
+ result[i] = this.Data[i].Time;
+ }
+
+ return result;
+ }
+
+ this.GetUp = function () //上涨家数
+ {
+ var result = [];
+ for (var i in this.Data) {
+ result[i] = this.Data[i].Up;
+ }
+
+ return result;
+ }
+
+ this.GetDown = function () //下跌家数
+ {
+ var result = [];
+ for (var i in this.Data) {
+ result[i] = this.Data[i].Down;
+ }
+
+ return result;
+ }
+
+ this.GetYear=function()
+ {
+ var result=new Array();
+ for(var i in this.Data)
+ {
+ result[i]=parseInt(this.Data[i].Date/10000);
+ }
+
+ return result;
+ }
+
+ this.GetMonth=function()
+ {
+ var result=new Array();
+ for(var i in this.Data)
+ {
+ result[i]=parseInt(this.Data[i].Date%10000/100);
+ }
+
+ return result;
+ }
+
+ //分时图均价
+ this.GetAvPrice=function()
+ {
+ var result=new Array();
+ for(var i in this.Data)
+ {
+ var value=this.Data[i].AvPrice;
+ if (ChartData.IsNumber(value))
+ result[i]=value;
+ else
+ result[i]=0;
+ }
+
+ return result;
+ }
+
+ //获取数据日期和时间范围
+ this.GetDateRange=function()
+ {
+ if (!this.Data || this.Data.length<=0) return null;
+
+ var start=this.Data[0];
+ var end=this.Data[this.Data.length-1];
+ var range={ Start:{Date:start.Date}, End:{Date:end.Date} };
+ if (ChartData.IsNumber(start.Time)) range.Start.Time=start.Time;
+ if (ChartData.IsNumber(end.Time)) range.End.Time=end.Time;
+
+ return range;
+ }
+
+
+ this.GetDateIndex = function (data) //日期转化 对应数据索引
+ {
+ for (var i = 0, j = 0; i < this.Data.length;)
+ {
+ var date = this.Data[i].Date;
+
+ if (j >= data.length) break;
+
+ var dateItem = data[j];
+
+ if (dateItem.Date == date)
+ {
+ dateItem.Index = i;
+ ++j;
+ }
+ else if (dateItem.Date < date)
+ {
+ ++j;
+ }
+ else
+ {
+ ++i;
+ }
+ }
+ }
+
+
+ this.GetDateTimeIndex = function (data) //日期 时间转化 对应数据索引
+ {
+ for (var i = 0, j = 0; i < this.Data.length;)
+ {
+ var date = this.Data[i].Date;
+ var time = this.Data[i].Time;
+
+ if (j >= data.length) break;
+
+ var dateTimeItem = data[j];
+
+ if (dateTimeItem.Date == date && dateTimeItem.Time == time)
+ {
+ dateTimeItem.Index = i;
+ ++j;
+ }
+ else if (dateTimeItem.Date < date || (dateTimeItem.Date == date && dateTimeItem.Time < time))
+ {
+ ++j;
+ }
+ else
+ {
+ ++i;
+ }
+ }
+ }
+
+ this.GetMinutePeriodData=function(period)
+ {
+ if (DataPlus.GetMinutePeriodData) return DataPlus.GetMinutePeriodData(period, this.Data, this);
+
+ if (period > CUSTOM_MINUTE_PERIOD_START && period <= CUSTOM_MINUTE_PERIOD_END)
+ return this.GetMinuteCustomPeriodData(period - CUSTOM_MINUTE_PERIOD_START);
+
+ var result = [];
+ var periodDataCount = 5;
+ if (period == 5)
+ periodDataCount = 5;
+ else if (period == 6)
+ periodDataCount = 15;
+ else if (period == 7)
+ periodDataCount = 30;
+ else if (period == 8)
+ periodDataCount = 60;
+ else if (period == 11)
+ periodDataCount = 120;
+ else if (period == 12)
+ periodDataCount = 240;
+ else
+ return this.Data;
+ var bFirstPeriodData = false;
+ var newData = null;
+ var preTime = null; //上一次的计算时间
+ for (var i = 0; i < this.Data.length; )
+ {
+ bFirstPeriodData = true;
+ for (var j = 0; j < periodDataCount && i < this.Data.length; ++i)
+ {
+ if (bFirstPeriodData)
+ {
+ newData = new HistoryData();
+ result.push(newData);
+ bFirstPeriodData = false;
+ }
+ var minData = this.Data[i];
+ if (minData == null)
+ {
+ ++j;
+ continue;
+ }
+ if (minData.Time == 925 && (preTime == null || preTime != 924)) //9:25, 9:30 不连续就不算个数
+ {
+ }
+ else if (minData.Time == 930 && (preTime == null || preTime != 929))
+ {
+ }
+ else if (minData.Time == 1300 && (preTime == null || preTime != 1259)) //1点的数据 如果不是连续的 就不算个数
+ {
+
+ }
+ else
+ ++j;
+ newData.Date = minData.Date;
+ newData.Time = minData.Time;
+ preTime = newData.Time;
+ if (minData.Open==null || minData.Close==null)
+ continue;
+ if (newData.Open==null || newData.Close==null)
+ {
+ newData.Open=minData.Open;
+ newData.High=minData.High;
+ newData.Low=minData.Low;
+ newData.YClose=minData.YClose;
+ newData.Close=minData.Close;
+ newData.Vol=minData.Vol;
+ newData.Amount=minData.Amount;
+ newData.Position = minData.Position;
+ newData.FlowCapital = minData.FlowCapital;
+ }
+ else
+ {
+ if (newData.HighminData.Low)
+ newData.Low=minData.Low;
+ newData.Close=minData.Close;
+ newData.Vol+=minData.Vol;
+ newData.Amount+=minData.Amount;
+ newData.Position = minData.Position;
+ newData.FlowCapital = minData.FlowCapital;
+ }
+
+ if (i + 1 < this.Data.length) //判断下一个数据是否是不同日期的
+ {
+ var nextItem = this.Data[i + 1];
+ if (nextItem && nextItem.Date != minData.Date) //不同日期的, 周期结束
+ {
+ ++i;
+ break;
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ //自定义分钟
+ this.GetMinuteCustomPeriodData = function (count)
+ {
+ var result = new Array();
+ var periodDataCount = count;
+ var bFirstPeriodData = false;
+ var newData = null;
+ for (var i = 0; i < this.Data.length;)
+ {
+ bFirstPeriodData = true;
+ for (var j = 0; j < periodDataCount && i < this.Data.length; ++i, ++j)
+ {
+ if (bFirstPeriodData)
+ {
+ newData = new HistoryData();
+ result.push(newData);
+ bFirstPeriodData = false;
+ }
+ var minData = this.Data[i];
+ if (minData == null) continue;
+
+ newData.Date = minData.Date;
+ newData.Time = minData.Time;
+ if (minData.Open == null || minData.Close == null) continue;
+ if (newData.Open == null || newData.Close == null)
+ {
+ newData.Open = minData.Open;
+ newData.High = minData.High;
+ newData.Low = minData.Low;
+ newData.YClose = minData.YClose;
+ newData.Close = minData.Close;
+ newData.Vol = minData.Vol;
+ newData.Amount = minData.Amount;
+ newData.FlowCapital = minData.FlowCapital;
+ newData.Position = minData.Position;
+ }
+ else
+ {
+ if (newData.High < minData.High) newData.High = minData.High;
+ if (newData.Low > minData.Low) newData.Low = minData.Low;
+ newData.Close = minData.Close;
+ newData.Vol += minData.Vol;
+ newData.Amount += minData.Amount;
+ newData.FlowCapital = minData.FlowCapital;
+ newData.Position = minData.Position;
+ }
+ }
+ }
+ return result;
+ }
+
+ this.GetDayPeriodData=function(period)
+ {
+ if (period > CUSTOM_DAY_PERIOD_START && period <= CUSTOM_DAY_PERIOD_END) //自定义周期
+ return this.GetDayCustomPeriodData(period - CUSTOM_DAY_PERIOD_START);
+
+ var isBit = MARKET_SUFFIX_NAME.IsBIT(this.Symbol);
+ var result=[];
+ var index=0;
+ var startDate=0;
+ var weekCount = 2;
+ var newData=null;
+ for(var i in this.Data)
+ {
+ var isNewData=false;
+ var dayData=this.Data[i];
+
+ switch(period)
+ {
+ case 1: //周线
+ if (isBit) var fridayDate = ChartData.GetSunday(dayData.Date);
+ else var fridayDate=ChartData.GetFirday(dayData.Date);
+ if (fridayDate!=startDate)
+ {
+ isNewData=true;
+ startDate=fridayDate;
+ }
+ break;
+ case 21: //双周
+ if (isBit) var fridayDate = ChartData.GetSunday(dayData.Date);
+ else var fridayDate = ChartData.GetFirday(dayData.Date);
+ if (fridayDate != startDate)
+ {
+ ++weekCount;
+ if (weekCount >= 2)
+ {
+ isNewData = true;
+ weekCount = 0;
+ }
+ startDate = fridayDate;
+ }
+ break;
+ case 2: //月线
+ if (parseInt(dayData.Date/100)!=parseInt(startDate/100))
+ {
+ isNewData=true;
+ startDate=dayData.Date;
+ }
+ break;
+ case 3: //年线
+ if (parseInt(dayData.Date/10000)!=parseInt(startDate/10000))
+ {
+ isNewData=true;
+ startDate=dayData.Date;
+ }
+ break;
+ case 9: //季线
+ var now = ChartData.GetQuarter(dayData.Date);
+ now = parseInt(dayData.Date / 10000) * 10 + now;
+ var last = ChartData.GetQuarter(startDate);
+ last = parseInt(startDate / 10000) * 10 + last;
+ if (now != last)
+ {
+ isNewData = true;
+ startDate = dayData.Date;
+ }
+ break;
+ }
+
+ if (isNewData)
+ {
+ newData=new HistoryData();
+ newData.Date=dayData.Date;
+ result.push(newData);
+
+ if (dayData.Open==null || dayData.Close==null) continue;
+
+ newData.Open=dayData.Open;
+ newData.High=dayData.High;
+ newData.Low=dayData.Low;
+ newData.YClose=dayData.YClose;
+ newData.Close=dayData.Close;
+ newData.Vol=dayData.Vol;
+ newData.Amount=dayData.Amount;
+ newData.FlowCapital = dayData.FlowCapital;
+ newData.Position = dayData.Position;
+ }
+ else
+ {
+ if (newData==null) continue;
+ if (dayData.Open==null || dayData.Close==null) continue;
+
+ if (newData.Open==null || newData.Close==null)
+ {
+ newData.Open=dayData.Open;
+ newData.High=dayData.High;
+ newData.Low=dayData.Low;
+ newData.YClose=dayData.YClose;
+ newData.Close=dayData.Close;
+ newData.Vol=dayData.Vol;
+ newData.Amount=dayData.Amount;
+ newData.FlowCapital = dayData.FlowCapital;
+ newData.Position = dayData.Position;
+ }
+ else
+ {
+ if (newData.HighdayData.Low) newData.Low=dayData.Low;
+
+ newData.Close=dayData.Close;
+ newData.Vol+=dayData.Vol;
+ newData.Amount+=dayData.Amount;
+ newData.Date=dayData.Date;
+ newData.FlowCapital = dayData.FlowCapital;
+ newData.Position = dayData.Position;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ this.GetDayCustomPeriodData = function (count) //自定义日线周期
+ {
+ var result = [];
+ var periodDataCount = count;
+ var bFirstPeriodData = false;
+ var newData = null;
+ for (var i = 0; i < this.Data.length;)
+ {
+ bFirstPeriodData = true;
+ for (var j = 0; j < periodDataCount && i < this.Data.length; ++i, ++j)
+ {
+ if (bFirstPeriodData)
+ {
+ newData = new HistoryData();
+ result.push(newData);
+ bFirstPeriodData = false;
+ }
+ var dayData = this.Data[i];
+ if (dayData == null) continue;
+
+ newData.Date = dayData.Date;
+
+ if (dayData.Open == null || dayData.Close == null) continue;
+ if (newData.Open == null || newData.Close == null)
+ {
+ newData.Open = dayData.Open;
+ newData.High = dayData.High;
+ newData.Low = dayData.Low;
+ newData.YClose = dayData.YClose;
+ newData.Close = dayData.Close;
+ newData.Vol = dayData.Vol;
+ newData.Amount = dayData.Amount;
+ newData.FlowCapital = dayData.FlowCapital;
+ newData.Position = dayData.Position;
+ }
+ else
+ {
+ if (newData.High < dayData.High) newData.High = dayData.High;
+ if (newData.Low > dayData.Low) newData.Low = dayData.Low;
+ newData.Close = dayData.Close;
+ newData.Vol += dayData.Vol;
+ newData.Amount += dayData.Amount;
+ newData.Position = dayData.Position;
+ newData.FlowCapital = dayData.FlowCapital;
+ }
+ }
+ }
+ return result;
+ }
+
+ //周期数据 1=周 2=月 3=年 9=季
+ this.GetPeriodData=function(period)
+ {
+ if (period == 1 || period == 2 || period == 3 || period == 9 || period == 21 || (period > CUSTOM_DAY_PERIOD_START && period <= CUSTOM_DAY_PERIOD_END)) return this.GetDayPeriodData(period);
+ if (period == 5 || period == 6 || period == 7 || period == 8 || period == 11 || period == 12 ||(period > CUSTOM_MINUTE_PERIOD_START && period <= CUSTOM_MINUTE_PERIOD_END)) return this.GetMinutePeriodData(period);
+ }
+
+ //复权 0 不复权 1 前复权 2 后复权
+ this.GetRightDate=function(right)
+ {
+ var result=[];
+ if (this.Data.length<=0) return result;
+
+ if (right==1)
+ {
+ var index=this.Data.length-1;
+ var seed=1; //复权系数
+ var yClose=this.Data[index].YClose;
+
+ result[index]=HistoryData.Copy(this.Data[index]);
+
+ for(--index; index>=0; --index)
+ {
+ if (yClose!=this.Data[index].Close) break;
+ result[index]=HistoryData.Copy(this.Data[index]);
+ yClose=this.Data[index].YClose;
+ }
+
+ for(; index>=0; --index)
+ {
+ if(yClose!=this.Data[index].Close)
+ seed *= yClose/this.Data[index].Close;
+
+ result[index]=HistoryData.CopyRight(this.Data[index],seed);
+
+ yClose=this.Data[index].YClose;
+ }
+ }
+ else if (right==2)
+ {
+ var index=0;
+ var seed=1;
+ var close=this.Data[index].Close;
+ result[index]=HistoryData.Copy(this.Data[index]);
+
+ for(++index;index=overlayData.length)
+ {
+ result[i]=new HistoryData();
+ result[i].Date=date;
+ ++i;
+ continue;;
+ }
+
+ var overlayDate=overlayData[j].Date;
+
+ if (overlayDate==date)
+ {
+ result[i]=new HistoryData();
+ result[i].Date=overlayData[j].Date;
+ result[i].YClose=overlayData[j].YClose;
+ result[i].Open=overlayData[j].Open;
+ result[i].High=overlayData[j].High;
+ result[i].Low=overlayData[j].Low;
+ result[i].Close=overlayData[j].Close;
+ result[i].Vol=overlayData[j].Vol;
+ result[i].Amount=overlayData[j].Amount;
+
+ //涨跌家数数据
+ result[i].Stop = overlayData[j].Stop;
+ result[i].Up = overlayData[j].Up;
+ result[i].Down = overlayData[j].Down;
+ result[i].Unchanged = overlayData[j].Unchanged;
+
+ ++j;
+ ++i;
+ }
+ else if (overlayDate=overlayData.length)
+ {
+ result[i]=null;
+ ++i;
+ continue;;
+ }
+
+ var overlayDate=overlayData[j].Date;
+
+ if (overlayDate==date)
+ {
+ var item=new SingleData();
+ item.Date=overlayData[j].Date;
+ item.Value=overlayData[j].Value;
+ result[i]=item;
+ ++j;
+ ++i;
+ }
+ else if (overlayDate= overlayData.length)
+ {
+ result[i] = new SingleData();
+ result[i].Date = date;
+ result[i].Value = emptyValue;
+ ++i;
+ continue;;
+ }
+
+ var overlayDate = overlayData[j].Date;
+
+ if (overlayDate == date)
+ {
+ var item = new SingleData();
+ item.Date = overlayData[j].Date;
+ item.Value = overlayData[j].Value;
+ result[i] = item;
+ ++j;
+ ++i;
+ }
+ else if (overlayDate < date)
+ {
+ ++j;
+ }
+ else
+ {
+ result[i] = new SingleData();
+ result[i].Date = date;
+ result[i].Value = emptyValue;
+ ++i;
+ }
+ }
+
+ return result;
+ }
+
+
+ this.GetMinuteFittingData = function (overlayData) // 分钟数据拟合
+ {
+ var result = [];
+ for (var i = 0, j = 0; i < this.Data.length;)
+ {
+ var date = this.Data[i].Date;
+ var time = this.Data[i].Time;
+
+ if (j >= overlayData.length)
+ {
+ result[i] = null;
+ ++i;
+ continue;;
+ }
+
+ var overlayDate = overlayData[j].Date;
+ var overlayTime = overlayData[j].Time;
+ const overlayItem = overlayData[j];
+
+ if (overlayDate == date && overlayTime == time)
+ {
+ var item = new SingleData();
+ item.Date = overlayItem.Date;
+ item.Time = overlayItem.Time;
+ item.Value = overlayItem.Value;
+ result[i] = item;
+ ++j;
+ ++i;
+ }
+ else if (overlayDate < date || (overlayDate == date && overlayTime < time))
+ {
+ ++j;
+ }
+ else
+ {
+ var item = new SingleData();
+ item.Date = date;
+ item.Time = time;
+ result[i] = item;
+ ++i;
+ }
+ }
+
+ return result;
+ }
+
+ //把财报数据拟合到主图数据,返回 SingleData 数组
+ this.GetFittingFinanceData = function (financeData)
+ {
+ var result = [];
+
+ for (var i = 0, j = 0; i < this.Data.length;)
+ {
+ var date = this.Data[i].Date;
+
+ if (jfirstItem.Date || (date==firstItem.Date && time>=firstItem.Time))
+ {
+ break;
+ }
+ }
+
+ for(var j=0;i= overlayData.length) {
+ result[i] = null;
+ ++i;
+ continue;;
+ }
+
+ var overlayDate = overlayData[j].Date;
+
+ if (overlayDate == date) {
+ var item = new SingleData();
+ item.Date = overlayData[j].Date;
+ item.Value = overlayData[j].Value;
+ item.Text = overlayData[j].Text;
+ result[i] = item;
+ ++j;
+ ++i;
+ }
+ else if (preDate != null && preDate < overlayDate && date > overlayDate) {
+ var item = new SingleData();
+ item.Date = date;
+ item.OverlayDate = overlayData[j].Date;
+ item.Value = overlayData[j].Value;
+ item.Text = overlayData[j].Text;
+ result[i] = item;
+ ++j;
+ ++i;
+ }
+ else if (overlayDate < date) {
+ ++j;
+ }
+ else {
+ result[i] = new SingleData();
+ result[i].Date = date;
+ ++i;
+ }
+
+ preDate = date;
+ }
+
+ return result;
+ }
+
+
+ this.GetValue=function()
+ {
+ var result=new Array();
+ for(var i in this.Data)
+ {
+ if (this.Data[i]==null || this.Data[i].Value == null)
+ {
+ result[i] = null;
+ }
+ else
+ {
+ // console.log(this.Data[i].Value);
+ // console.log(i);
+ if (!isNaN(this.Data[i].Value))
+ result[i] = this.Data[i].Value;
+ else if (this.Data[i].Value instanceof Array) //支持数组
+ result[i] = this.Data[i].Value;
+ else
+ result[i] = null;
+ }
+ }
+
+ return result;
+ }
+
+ this.GetPeriodSingleData=function(period)
+ {
+ var result=new Array();
+ var index=0;
+ var startDate=0;
+ var newData=null;
+ for(var i in this.Data)
+ {
+ var isNewData=false;
+ var dayData=this.Data[i];
+ if (dayData==null || dayData.Date==null) continue;
+
+ switch(period)
+ {
+ case 1: //周线
+ var fridayDate=ChartData.GetFirday(dayData.Date);
+ if (fridayDate!=startDate)
+ {
+ isNewData=true;
+ startDate=fridayDate;
+ }
+ break;
+ case 2: //月线
+ if (parseInt(dayData.Date/100)!=parseInt(startDate/100))
+ {
+ isNewData=true;
+ startDate=dayData.Date;
+ }
+ break;
+ case 3: //年线
+ if (parseInt(dayData.Date/10000)!=parseInt(startDate/10000))
+ {
+ isNewData=true;
+ startDate=dayData.Date;
+ }
+ break;
+ }
+
+ if (isNewData)
+ {
+ newData=new SingleData();
+ newData.Date=dayData.Date;
+ newData.Value=dayData.Value;
+ result.push(newData);
+ }
+ else
+ {
+ if (newData==null) continue;
+ if (dayData.Value==null || isNaN(dayData.Value)) continue;
+ if (newData.Value==null || isNaN(newData.Value)) newData.Value=dayData.Value;
+ }
+ }
+
+ return result;
+ }
+
+ /*
+ 分钟数据方法
+ this.GetClose() 每分钟价格
+ this.GetVol() 每分钟成交量
+ */
+
+ //分钟均线
+ this.GetMinuteAvPrice=function()
+ {
+ var result=new Array();
+ for(var i in this.Data)
+ {
+ result[i]=this.Data[i].AvPrice;
+ }
+
+ return result;
+ }
+
+ this.MergeMinuteData = function (data) //合并数据
+ {
+ var sourceFirstItem = this.Data[0];
+ var firstItemID = 0;
+ var firstItem = null;
+ for (var i = 0; i < data.length; ++i) //查找比原始数据起始位置大的数据位置
+ {
+ var item = data[i];
+ if (item.Date >sourceFirstItem.Date)
+ {
+ firstItemID = i;
+ firstItem = item;
+ break;
+ }
+
+ if (item.Date == sourceFirstItem.Date && item.Time >= sourceFirstItem.Time)
+ {
+ firstItemID = i;
+ firstItem = item;
+ break;
+ }
+ }
+ if (firstItem == null) return false;
+
+ var index = null;
+ var bFind = false; //第1个数据是否完全匹配
+ for (var i = this.Data.length - 1; i >= 0; --i)
+ {
+ var date = this.Data[i].Date;
+ var time = this.Data[i].Time;
+
+ if (firstItem.Date > date || (firstItem.Date == date && firstItem.Time >= time) )
+ {
+ index = i;
+ if (firstItem.Date == date && firstItem.Time == time) bFind = true;
+ break;
+ }
+ }
+
+ if (index == null) return false;
+ var j = index;
+ var i = firstItemID;
+ if (bFind == true) //第1个数据匹配,覆盖
+ {
+ var item = data[i];
+ if (j - 1 > 0 && !item.YClose) item.YClose = this.Data[j - 1].Close; //前收盘如果没有就是上一记录的收盘
+ var newItem = HistoryData.Copy(item);
+ this.Data[j] = newItem;
+ ++j;
+ ++i;
+ }
+ else
+ {
+ ++j;
+ }
+
+ for (; i < data.length;)
+ {
+ var item = data[i];
+ if (j >= this.Data.length - 1)
+ {
+ if (j - 1 > 0 && !item.YClose) item.YClose = this.Data[j - 1].YClose; //前收盘如果没有就是上一记录的收盘
+ var newItem = HistoryData.Copy(item);
+ this.Data[j] = newItem;
+ ++j;
+ ++i;
+ }
+ else
+ {
+ var oldItem = this.Data[j];
+ if (oldItem.Date == item.Date && oldItem.Time == item.Time) //更新数据
+ {
+ HistoryData.CopyTo(oldItem, item);
+ ++j;
+ ++i;
+ }
+ else
+ {
+ ++j;
+ }
+ }
+ }
+
+ //console.log('[ChartData::MergeMinuteData] ', this.Data, data);
+ return true;
+ }
+
+ //日线拟合交易数据, 不做平滑处理
+ this.GetFittingTradeData=function(tradeData, nullValue, bExactMatch)
+ {
+ var result=[];
+ var bMatch=false;
+ for(var i=0,j=0;idate)
+ {
+ var item=new SingleData();
+ item.Date=date;
+ item.Value=nullValue;
+ result[i]=item;
+ ++i;
+ continue;
+ }
+ }
+
+ if (j+1date || (tradeData[j].Date==date && tradeData[j].Time>time))
+ {
+ var item=new SingleData();
+ item.Date=date;
+ item.Time=time;
+ item.Value=nullValue;
+ result[i]=item;
+ ++i;
+ continue;
+ }
+ }
+
+ if (j+1 0)
+ {
+ var prevTimestamp = (24 * 60 * 60 * 1000) * (7 - day);
+ timestamp += prevTimestamp;
+ }
+
+ date.setTime(timestamp);
+ var sundayDate = date.getFullYear() * 10000 + (date.getMonth() + 1) * 100 + date.getDate();
+ var week = date.getDay();
+ return sundayDate;
+}
+
+ChartData.GetQuarter = function (value)
+{
+ var month = parseInt(value % 10000 / 100);
+ if (month == 1 || month == 2 || month == 3) return 1;
+ else if (month == 4 || month == 5 || month == 6) return 2;
+ else if (month == 7 || month == 8 || month == 9) return 3;
+ else if (month == 10 || month == 11 || month == 12) return 4;
+ else return 0;
+}
+
+//是否是日线周期 0=日线 1=周线 2=月线 3=年线 9=季线 21=双周 [40001-50000) 自定义日线 (isIncludeBase 是否包含基础日线周期)
+var CUSTOM_DAY_PERIOD_START = 40000, CUSTOM_DAY_PERIOD_END = 49999;
+ChartData.IsDayPeriod = function (period, isIncludeBase)
+{
+ if (period == 1 || period == 2 || period == 3 || period == 9 || period==21 ) return true;
+ if (period > CUSTOM_DAY_PERIOD_START && period <= CUSTOM_DAY_PERIOD_END) return true;
+ if (period == 0 && isIncludeBase == true) return true;
+
+ return false;
+}
+
+//是否是分钟周期 4=1分钟 5=5分钟 6=15分钟 7=30分钟 8=60分钟 11=2h 12=4h[20001-30000) 自定义分钟 (isIncludeBase 是否包含基础1分钟周期)
+var CUSTOM_MINUTE_PERIOD_START = 20000, CUSTOM_MINUTE_PERIOD_END = 29999;
+ChartData.IsMinutePeriod = function (period, isIncludeBase)
+{
+ if (period == 5 || period == 6 || period == 7 || period == 8 || period == 11 || period == 12) return true;
+ if (period > CUSTOM_MINUTE_PERIOD_START && period <= CUSTOM_MINUTE_PERIOD_END) return true;
+ if (period == 4 && isIncludeBase == true) return true;
+
+ return false;
+}
+
+//是否是秒周期 [30001-32000)
+var CUSTOM_SECOND_PERIOD_START = 30000, CUSTOM_SECOND_PERIOD_END = 32000;
+ChartData.IsSecondPeriod = function (period)
+{
+ if (period > CUSTOM_SECOND_PERIOD_START && period <= CUSTOM_SECOND_PERIOD_END) return true;
+ return false;
+}
+
+
+//是否是分笔图
+ChartData.IsTickPeriod = function (period)
+{
+ return period == 10;
+}
+
+//获取周期名字
+ChartData.GetPeriodName = function (period)
+{
+ var mapName = new Map(
+ [
+ [0, '日线'], [1, '周线'], [2, '月线'], [3, '年线'], [9, '季线'], [21, '双周'],
+ [4, '1分'], [5, '5分'], [6, '15分'], [7, '30分'], [8, '60分'], [11, '2小时'], [12, '4小时'],
+ [10, '分笔']
+ ]);
+
+ if (mapName.has(period)) return mapName.get(period);
+
+ return '';
+}
+
+function Rect(x, y, width, height)
+{
+ this.Left = x,
+ this.Top = y;
+ this.Right = x + width;
+ this.Bottom = y + height;
+
+ this.IsPointIn = function (x, y)
+ {
+ if (x >= this.Left && x <= this.Right && y >= this.Top && y <= this.Bottom) return true;
+ return false;
+ }
+}
+
+//修正线段有毛刺
+function ToFixedPoint(value)
+{
+ //return value;
+ return parseInt(value) + 0.5;
+}
+
+function ToFixedRect(value)
+{
+ var rounded;
+ return rounded = (0.5 + value) << 0;
+}
+
+var JSCHART_EVENT_ID =
+{
+ RECV_INDEX_DATA: 2, //接收指标数据
+ RECV_HISTROY_DATA: 3,//接收到历史数据
+ RECV_TRAIN_MOVE_STEP: 4, //接收K线训练,移动一次K线
+ CHART_STATUS: 5, //每次Draw() 以后会调用
+ BARRAGE_PLAY_END: 6, //单个弹幕播放完成
+ RECV_START_AUTOUPDATE: 9, //开始自动更新
+ RECV_STOP_AUTOUPDATE: 10, //停止自动更新
+ ON_TITLE_DRAW: 12, //标题信息绘制事件
+ RECV_MINUTE_DATA: 14, //分时图数据到达
+ ON_CLICK_INDEXTITLE:15, //点击指标标题事件
+ RECV_KLINE_UPDATE_DATA: 16, //K线日,分钟更新数据到达
+ ON_INDEXTITLE_DRAW: 19, //指标标题重绘事件
+ ON_CUSTOM_VERTICAL_DRAW: 20, //自定义X轴绘制事件
+ ON_ENABLE_SPLASH_DRAW:22, //开启/关闭过场动画事件
+
+ ON_DRAW_DEPTH_TOOLTIP:25, //绘制深度图tooltip事件
+ ON_PHONE_TOUCH:27, //手势点击事件 包含 TouchStart 和 TouchEnd
+
+ ON_SPLIT_YCOORDINATE:29, //分割Y轴及格式化刻度文字
+}
+
+function PhoneDBClick()
+{
+ this.Start=[];
+
+ this.Clear=function()
+ {
+ this.Start=[];
+ }
+
+ this.AddTouchStart=function(x, y, time)
+ {
+ if (this.Start.length>0)
+ {
+ var item=this.Start[this.Start.length-1];
+ var spanTime=time-item.Time;
+ if (spanTime>0 && spanTime<300)
+ {
+ this.Start.push({ X:x, Y:y, Time:time });
+ }
+ else
+ {
+ this.Start=[];
+ }
+ }
+ else
+ {
+ this.Start.push({ X:x, Y:y, Time:time });
+ }
+ }
+
+ this.IsVaildDBClick=function()
+ {
+ if (this.Start.length==2) return true;
+
+ return false;
+ }
+
+ this.AddTouchEnd=function(time)
+ {
+ if (this.Start.length<=0) return;
+
+ var item=this.Start[this.Start.length-1];
+ var spanTime=time-item.Time;
+ if (spanTime>=0 && spanTime<150)
+ {
+
+ }
+ else
+ {
+ this.Start=[];
+ }
+ }
+}
+
+//导出统一使用JSCommon命名空间名
+module.exports =
+{
+ JSCommonData:
+ {
+ HistoryData: HistoryData,
+ ChartData: ChartData,
+ SingleData: SingleData,
+ MinuteData: MinuteData,
+ Rect: Rect,
+ DataPlus: DataPlus,
+ JSCHART_EVENT_ID:JSCHART_EVENT_ID,
+ PhoneDBClick:PhoneDBClick,
+ },
+
+ //单个类导出
+ JSCommon_ChartData: ChartData,
+ JSCommon_HistoryData: HistoryData,
+ JSCommon_SingleData: SingleData,
+ JSCommon_MinuteData: MinuteData,
+ JSCommon_CUSTOM_DAY_PERIOD_START: CUSTOM_DAY_PERIOD_START,
+ JSCommon_CUSTOM_DAY_PERIOD_END: CUSTOM_DAY_PERIOD_END,
+ JSCommon_CUSTOM_MINUTE_PERIOD_START: CUSTOM_MINUTE_PERIOD_START,
+ JSCommon_CUSTOM_MINUTE_PERIOD_END: CUSTOM_MINUTE_PERIOD_END,
+ JSCommon_CUSTOM_SECOND_PERIOD_START: CUSTOM_SECOND_PERIOD_START,
+ JSCommon_CUSTOM_SECOND_PERIOD_END: CUSTOM_SECOND_PERIOD_END,
+ JSCommon_Rect: Rect,
+ JSCommon_DataPlus: DataPlus,
+ JSCommon_Guid: Guid,
+ JSCommon_ToFixedPoint: ToFixedPoint,
+ JSCommon_ToFixedRect: ToFixedRect,
+ JSCommon_JSCHART_EVENT_ID:JSCHART_EVENT_ID,
+ JSCommon_PhoneDBClick:PhoneDBClick,
+};
\ No newline at end of file
diff --git a/uni_modules/jones-hqchart2/js_sdk/umychart.explainer.wechat.js b/uni_modules/jones-hqchart2/js_sdk/umychart.explainer.wechat.js
new file mode 100644
index 0000000..825b53d
--- /dev/null
+++ b/uni_modules/jones-hqchart2/js_sdk/umychart.explainer.wechat.js
@@ -0,0 +1,1030 @@
+/*
+ copyright (c) 2018 jones
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ 开源项目 https://github.com/jones2000/HQChart
+
+ jones_2000@163.com
+
+ 分析家脚本翻译器
+*/
+
+import { JSConsole } from "./umychart.console.wechat.js"
+
+import {
+ JSCommonComplier_ErrorHandler as ErrorHandler,
+ JSCommonComplier_JSComplier as JSComplier,
+ JSCommonComplier_JSParser as JSParser,
+ JSCommonComplier_Syntax as Syntax,
+ JS_EXECUTE_JOB_ID as JS_EXECUTE_JOB_ID,
+ g_JSComplierResource as g_JSComplierResource,
+} from "./umychart.complier.wechat";
+
+import
+{
+ JSCommonSplit_IFrameSplitOperator as IFrameSplitOperator,
+} from './umychart.framesplit.wechat.js'
+
+
+//脚本说明
+function JSExplainer(ast,option)
+{
+ this.AST=ast;
+ this.ErrorHandler=new ErrorHandler();
+ this.ErrorCallback; //执行错误回调
+ this.UpdateUICallback;
+ this.CallbackParam;
+ this.JobList=[]; //执行的任务队列
+ this.VarTable=new Map(); //变量表
+ this.OutVarTable=[]; //输出变量
+
+ //脚本自动变量表, 只读
+ this.ConstVarTable=new Map(
+ [
+ //个股数据
+ ['CLOSE',"收盘价"],['VOL',"成交量"],['OPEN',"开盘价"],['HIGH',"最高价"],['LOW',"最低价"],['AMOUNT',"成交量"],
+ ['C',"收盘价"],['V',"成交量"],['O',"开盘价"],['H',"最高价"],['L',"最低价"],['AMO',"成交量"],
+ ['VOLR',"量比"], ['VOLINSTK',"持仓量"], ["OPI","持仓量"], ["ZSTJJ","均价"], ["QHJSJ","结算价"], ["SETTLE", "结算价"],
+
+ //日期类
+ ['DATE',"日期"],['YEAR',"年份"],['MONTH',"月份"],['PERIOD', "周期"],['WEEK',"星期"],["TIME","时间"],
+
+ //大盘数据
+ ['INDEXA',"大盘成交额"],['INDEXC',"大盘收盘价"],['INDEXH',"大盘最高价"],['INDEXL',"大盘最低价"],['INDEXO',"大盘开盘价"],['INDEXV',"大盘成交量"],
+ ['INDEXADV',"大盘上涨家数"],['INDEXDEC',"´大盘下跌家数"],
+
+ ["ADVANCE","上涨家数"], ['DECLINE', "下跌家数"],
+
+ ['FROMOPEN',"当前离开盘分钟数"],
+ ['TOTALFZNUM', "总分钟数"],
+
+ ['CURRBARSCOUNT',"到最后交易的周期"], //到最后交易日的周期数
+ ['TOTALBARSCOUNT',"总的周期数"],
+ ['ISLASTBAR',"是否是最后一个周期"], //判断是否为最后一个周期
+ ['BARSTATUS',"数据位置状态"], //BARSTATUS返回数据位置信息,1表示第一根K线,2表示最后一个数据,0表示中间位置.
+
+ ['CAPITAL',"当前流通股本(手)"], ["TOTALCAPITAL","当前总股本(手)"],
+ ['EXCHANGE',"换手率"], //换手率
+ ['SETCODE', "市场类型"], //市场类型
+ ['CODE',"品种代码"], //品种代码
+ ['STKNAME',"品种名称"], //品种名称
+ ["TQFLAG","当前复权状态"], //TQFLAG 当前的复权状态,0:无复权 1:前复权 2:后复权
+
+ ['HYBLOCK',"所属行业"], //所属行业板块
+ ['DYBLOCK',"所属地域"], //所属地域板块
+ ['GNBLOCK',"所属概念"], //所属概念
+ ["FGBLOCK","所属风格板块"],
+ ["ZSBLOCK","所属指数板块"],
+ ["ZHBLOCK",'所属组合板块'],
+ ["ZDBLOCK",'所属自定义板块'],
+ ["HYZSCODE","所属行业的板块指数代码"],
+
+ ["GNBLOCKNUM","所属概念板块的个数"],
+ ["FGBLOCKNUM","所属风格板块的个数"],
+ ["ZSBLOCKNUM","所属指数板块的个数"],
+ ["ZHBLOCKNUM","所属组合板块的个数"],
+ ["ZDBLOCKNUM","所属自定义板块的个数"],
+
+ ["HYSYL","指数市盈率或个股所属行业的市盈率"],
+ ["HYSJL","指数市净率或个股所属行业的市净率"],
+
+ ['DRAWNULL',"无效数据"]
+
+ ]);
+
+ if (option)
+ {
+ if (option.Callback) this.UpdateUICallback=option.Callback;
+ if (option.CallbackParam) this.CallbackParam=option.CallbackParam;
+ if (option.Arguments) this.Arguments=option.Arguments;
+ }
+
+ this.Run=function()
+ {
+ try
+ {
+ this.OutVarTable=[];
+ this.VarTable=new Map();
+ JSConsole.Complier.Log('[JSExecute::JSExplainer] Load Arguments', this.Arguments);
+ for(let i in this.Arguments) //预定义的变量
+ {
+ let item =this.Arguments[i];
+ this.VarTable.set(item.Name,item.Value);
+ }
+
+ let data=this.RunAST();//执行脚本
+ JSConsole.Complier.Log('[JSExplainer.Run] explain finish', data);
+ if (this.UpdateUICallback) //回调发送结果, 可以支持异步
+ {
+ JSConsole.Complier.Log('[JSExplainer.Run] invoke UpdateUICallback.');
+ this.UpdateUICallback(data);
+ }
+ }
+ catch(error)
+ {
+ JSConsole.Complier.Log('[JSExplainer.Run] throw error ', error);
+ if (this.ErrorCallback)
+ {
+ this.ErrorCallback(error, this.OutVarTable);
+ }
+ }
+ }
+
+
+ this.RunAST=function()
+ {
+ if (!this.AST) this.ThrowError();
+ if (!this.AST.Body) this.ThrowError();
+
+ for(let i in this.AST.Body)
+ {
+ let item =this.AST.Body[i];
+ this.VisitNode(item);
+
+ //输出变量
+ if (item.Type==Syntax.ExpressionStatement && item.Expression)
+ {
+ if (item.Expression.Type==Syntax.AssignmentExpression)
+ {
+ if (item.Expression.Operator==':' && item.Expression.Left)
+ {
+ let assignmentItem=item.Expression;
+ let varName=assignmentItem.Left.Name;
+ let outVar=`输出${varName}: ${this.VarTable.get(varName)}`;
+ this.OutVarTable.push({ Name:varName, Data:outVar,Type:0});
+ }
+ else if (item.Expression.Operator==':=' && item.Expression.Left)
+ {
+ let assignmentItem=item.Expression;
+ let varName=assignmentItem.Left.Name;
+ let outVar=`赋值${varName}: ${this.VarTable.get(varName)}`;
+ this.OutVarTable.push({ Name:varName, Data:outVar,Type:0, IsOut:false });
+ }
+ }
+ else if (item.Expression.Type==Syntax.CallExpression)
+ {
+ let callItem=item.Expression;
+ if (this.IsDrawFunction(callItem.Callee.Name))
+ {
+ let outVar=callItem.Out;
+ var drawName=callItem.Callee.Name;
+ this.OutVarTable.push({Name:drawName, Draw:`输出: ${outVar}`, Type:1});
+ }
+ else
+ {
+ let outVar=callItem.Out;
+ varName=`__temp_c_${callItem.Callee.Name}_${i}__`;
+ this.OutVarTable.push({Name:varName, Data:`输出: ${outVar}`,Type:0, NoneName:true});
+ }
+ }
+ else if (item.Expression.Type==Syntax.Identifier)
+ {
+ let varName=item.Expression.Name;
+ let outVar=this.ReadVariable(varName,item.Expression);
+ varName="__temp_i_"+i+"__";
+ this.OutVarTable.push({Name:varName, Data:`输出: ${outVar}`, Type:0, NoneName:true});
+ }
+ else if (item.Expression.Type==Syntax.Literal) //常量
+ {
+ let outVar=item.Expression.Value;
+ if (IFrameSplitOperator.IsString(outVar) && outVar.indexOf("$")>0)
+ outVar=this.GetOtherSymbolExplain({ Literal:outVar }, item);
+ varName="__temp_li_"+i+"__";
+ var type=0;
+ this.OutVarTable.push({Name:varName, Data:`输出: ${outVar}`, Type:0, NoneName:true});
+ }
+ else if (item.Expression.Type==Syntax.BinaryExpression) // CLOSE+OPEN;
+ {
+ var varName="__temp_b_"+i+"__";
+ let outVar=item.Expression.Out;
+ this.OutVarTable.push({Name:varName, Data:`输出: ${outVar}`,Type:0, NoneName:true});
+ }
+ else if (item.Expression.Type==Syntax.LogicalExpression) //逻辑语句 如 T1 AND T2
+ {
+ var varName="__temp_l_"+i+"__";
+ let outVar=item.Expression.Out;
+ this.OutVarTable.push({Name:varName, Data:`输出: ${outVar}`,Type:0, NoneName:true});
+ }
+ else if (item.Expression.Type==Syntax.SequenceExpression)
+ {
+ let varName;
+ let drawName;
+ let draw;
+ let color;
+ let lineWidth;
+ let colorStick=false;
+ let pointDot=false;
+ let circleDot=false;
+ let lineStick=false;
+ let stick=false;
+ let volStick=false;
+ let isShow=true;
+ let isExData=false;
+ let isDotLine=false;
+ let isOverlayLine=false; //叠加线
+ var isNoneName=false;
+ //显示在位置之上,对于DRAWTEXT和DRAWNUMBER等函数有用,放在语句的最后面(不能与LINETHICK等函数共用),比如:
+ //DRAWNUMBER(CLOSE>OPEN,HIGH,CLOSE),DRAWABOVE;
+ var isDrawAbove=false;
+ for(let j in item.Expression.Expression)
+ {
+ let itemExpression=item.Expression.Expression[j];
+ if (itemExpression.Type==Syntax.AssignmentExpression && itemExpression.Operator==':' && itemExpression.Left)
+ {
+ varName=itemExpression.Left.Name;
+ let varValue=this.VarTable.get(varName);
+ this.VarTable.set(varName,varValue); //把常量放到变量表里
+ }
+ else if (itemExpression.Type==Syntax.Identifier)
+ {
+ let value=itemExpression.Name;
+ if (value==='COLORSTICK') colorStick=true;
+ else if (value==='POINTDOT') pointDot=true;
+ else if (value==='CIRCLEDOT') circleDot=true;
+ else if (value==='DOTLINE') isDotLine=true;
+ else if (value==='LINESTICK') lineStick=true;
+ else if (value==='STICK') stick=true;
+ else if (value==='VOLSTICK') volStick=true;
+ else if (value==="DRAWABOVE") isDrawAbove=true;
+ else if (value.indexOf('COLOR')==0) color=value;
+ else if (value.indexOf('LINETHICK')==0) lineWidth=value;
+ else if (value.indexOf('NODRAW')==0) isShow=false;
+ else if (value.indexOf('EXDATA')==0) isExData=true; //扩展数据, 不显示再图形里面
+ else if (value.indexOf('LINEOVERLAY')==0) isOverlayLine=true;
+ else
+ {
+ varName=itemExpression.Name;
+ let varValue=this.ReadVariable(varName,itemExpression);
+ varName="__temp_si_"+i+"__";
+ isNoneName=true;
+ this.VarTable.set(varName,varValue); //放到变量表里
+ }
+ }
+ else if(itemExpression.Type==Syntax.Literal) //常量
+ {
+ let aryValue=itemExpression.Value;
+ varName=itemExpression.Value.toString();
+ isNoneName=true;
+ this.VarTable.set(varName,aryValue); //把常量放到变量表里
+ }
+ else if (itemExpression.Type==Syntax.CallExpression)
+ {
+ if (this.IsDrawFunction(itemExpression.Callee.Name))
+ {
+ draw=itemExpression.Out;
+ drawName=itemExpression.Callee.Name;
+ }
+ else
+ {
+ let varValue=itemExpression.Out;
+ varName=`__temp_sc_${itemExpression.Callee.Name}_${i}__`;
+ isNoneName=true;
+ this.VarTable.set(varName,varValue);
+ }
+ }
+ else if (itemExpression.Type==Syntax.BinaryExpression)
+ {
+ varName="__temp_sb_"+i+"__";
+ let aryValue=itemExpression.Out;
+ isNoneName=true;
+ this.VarTable.set(varName,aryValue);
+ }
+ }
+
+ var outValue;
+ if (draw) outValue=`输出: ${draw}`;
+ else if (isNoneName) outValue=`输出: ${this.VarTable.get(varName)}`;
+ else outValue=`输出${varName}: ${this.VarTable.get(varName)}`;
+
+ if (color) outValue+=`,颜色${this.GetColorExplain(color)}`;
+ if (lineWidth) outValue+=`,线段粗细${this.GetLineWidthExplain(lineWidth)}`;
+ if (isShow==false) outValue+=",不显示";
+ if (isDotLine==true) outValue+=",画虚线";
+ if (isDrawAbove==true) outValue+=',显示在位置之上';
+
+ if (pointDot && varName) //圆点
+ {
+ outValue+=",画小圆点线";
+ let value={Name:varName, Data:outValue, Radius:g_JSChartResource.POINTDOT.Radius, Type:3};
+ this.OutVarTable.push(value);
+ }
+ else if (circleDot && varName) //圆点
+ {
+ outValue+=",画小圆圈线";
+ let value={Name:varName, Data:outValue, Radius:g_JSChartResource.CIRCLEDOT.Radius, Type:3};
+ this.OutVarTable.push(value);
+ }
+ else if (lineStick && varName) //LINESTICK 同时画出柱状线和指标线
+ {
+ outValue+=",画出柱状线和指标线";
+ let value={Name:varName, Data:outValue, Type:4};
+ this.OutVarTable.push(value);
+ }
+ else if (stick && varName) //STICK 画柱状线
+ {
+ outValue+=",画柱状线";
+ let value={Name:varName, Data:outValue, Type:5};
+ this.OutVarTable.push(value);
+ }
+ else if (volStick && varName) //VOLSTICK 画彩色柱状线
+ {
+ outValue+=",画成交量柱状线";
+ let value={Name:varName, Data:outValue, Type:6};
+ this.OutVarTable.push(value);
+ }
+ else if (varName && color)
+ {
+ let value={Name:varName, Data:outValue, Color:color, Type:0};
+ this.OutVarTable.push(value);
+ }
+ else if (draw) //画图函数
+ {
+ var outVar={ Name:drawName, Data:outValue, Type:1 };
+ this.OutVarTable.push(outVar);
+ }
+ else if (colorStick && varName) //CYW: SUM(VAR4,10)/10000, COLORSTICK; 画上下柱子
+ {
+ outValue+=",画彩色柱状线";
+ let value={Name:varName, Data:outValue, Color:color, Type:2};
+ this.OutVarTable.push(value);
+ }
+ else if (varName)
+ {
+ let value={Name:varName, Data:outValue,Type:0};
+ this.OutVarTable.push(value);
+ }
+ }
+ }
+ }
+
+ JSConsole.Complier.Log('[JSExplainer::Run]', this.VarTable);
+ return this.OutVarTable;
+ }
+
+ this.VisitNode=function(node)
+ {
+ switch(node.Type)
+ {
+ case Syntax.SequenceExpression:
+ this.VisitSequenceExpression(node);
+ break;
+ case Syntax.ExpressionStatement:
+ this.VisitNode(node.Expression);
+ break;
+ case Syntax.AssignmentExpression:
+ this.VisitAssignmentExpression(node);
+ break;
+ case Syntax.BinaryExpression:
+ case Syntax.LogicalExpression:
+ this.VisitBinaryExpression(node);
+ break;
+ case Syntax.CallExpression:
+ this.VisitCallExpression(node);
+ break;
+ }
+ }
+
+ this.VisitSequenceExpression=function(node)
+ {
+ for(let i in node.Expression)
+ {
+ let item =node.Expression[i];
+ this.VisitNode(item);
+ }
+ }
+
+ //函数调用
+ this.VisitCallExpression=function(node)
+ {
+ let funcName=node.Callee.Name;
+ let args=[];
+ for(let i in node.Arguments)
+ {
+ let item=node.Arguments[i];
+ let value;
+ if (item.Type==Syntax.BinaryExpression || item.Type==Syntax.LogicalExpression)
+ value=this.VisitBinaryExpression(item);
+ else if (item.Type==Syntax.CallExpression)
+ value=this.VisitCallExpression(item);
+ else
+ value=this.GetNodeValue(item);
+ args.push(value);
+ }
+
+ JSConsole.Complier.Log('[JSExplainer::VisitCallExpression]' , funcName, '(', args.toString() ,')');
+
+ if (g_JSComplierResource.IsCustomFunction(funcName))
+ {
+ var data=this.Algorithm.CallCustomFunction(funcName, args, this.SymbolData, node);
+ node.Out=[];
+ node.Draw=null;
+
+ if (data)
+ {
+ if (data.Out) node.Out=data.Out;
+ if (data.Draw) node.Draw=data.Draw;
+ }
+
+ return node.Out;
+ }
+
+ node.Out=this.CallFunctionExplain(funcName, args, node);
+ return node.Out;
+ }
+
+ this.FUNCTION_INFO_LIST=new Map(
+ [
+ ["REF", { Name:"REF", Param:{ Count:2 }, ToString:function(args) { return `${args[1]}日前的${args[0]}`; } } ],
+ ["REFX", { Name:"REFX", Param:{ Count:2 }, ToString:function(args) { return `${args[1]}日后的${args[0]}`; } } ],
+ ["REFV", { Name:"REFV", Param:{ Count:2 }, ToString:function(args) { return `${args[1]}日前的(未作平滑处理)${args[0]}`; } } ],
+ ["REFXV", { Name:"REFXV", Param:{ Count:2 }, ToString:function(args) { return `${args[1]}日后的(未作平滑处理)${args[0]}`; } } ],
+
+ ["REFDATE", { Name:"REFDATE", Param:{ Count:2 }, ToString:function(args) { return `${args[1]}日${args[0]}`; } } ],
+ ["COUNT", { Name:"COUNT", Param:{ Count:2 }, ToString:function(args) { return `统计${args[1]}日中满足${args[0]}的天数`; } } ],
+ ["BARSLASTCOUNT", { Name:"BARSLASTCOUNT", Param:{ Count:1 }, ToString:function(args) { return `条件${args[0]}连续成立次数`; } } ],
+ ["BARSCOUNT", { Name:"BARSCOUNT", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}有效数据周期数`; } } ],
+ ["BARSLAST", { Name:"BARSLAST", Param:{ Count:1 }, ToString:function(args) { return `上次${args[0]}不为0距今天数`; } } ],
+ ["BARSNEXT", { Name:"BARSNEXT", Param:{ Count:1 }, ToString:function(args) { return `下次${args[0]}不为0距今天数`; } } ],
+ ["BARSSINCEN", { Name:"BARSSINCEN", Param:{ Count:2 }, ToString:function(args) { return `在${args[1]}周期内首次${args[0]}距今天数`; } } ],
+ ["BARSSINCE", { Name:"BARSSINCE", Param:{ Count:1 }, ToString:function(args) { return `首次${args[0]}距今天数`; } } ],
+ ["HHV", { Name:"HHV", Param:{ Count:2 }, ToString:function(args) { return `${args[1]}日内${args[0]}的最高值`; } } ],
+ ["LLV", { Name:"LLV", Param:{ Count:2 }, ToString:function(args) { return `${args[1]}日内${args[0]}的最低值`; } } ],
+
+ ["HOD", { Name:"HOD", Param:{ Count:2 }, ToString:function(args) { return `${args[1]}日内${args[0]}的高值名次`; } } ],
+ ["LOD", { Name:"LOD", Param:{ Count:2 }, ToString:function(args) { return `${args[1]}日内${args[0]}的低值名次`; } } ],
+ ["REVERSE", { Name:"REVERSE", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的相反数`; } } ],
+ ["FILTER", { Name:"FILTER", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日过滤`; } } ],
+ ["FILTERX", { Name:"FILTERX", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日反向过滤`; } } ],
+ ["SUMBARS", { Name:"SUMBARS", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}累加至${args[1]}的天数`; } } ],
+ ["MA", { Name:"MA", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日简单移动平均`; } } ],
+ ["SMA", { Name:"SMA", Param:{ Count:3 }, ToString:function(args) { return `${args[0]}的${args[1]}日[${args[2]}日权重]移动平均`; } } ],
+ ["MEMA", { Name:"MEMA", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日平滑移动平均`; } } ],
+ ["EMA", { Name:"EMA", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日指数移动平均`; } } ],
+ ["EXPMA", { Name:"EXPMA", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日指数移动平均`; } } ],
+ ["WMA", { Name:"WMA", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日加权移动平均`; } } ],
+ ["DMA", { Name:"DMA", Param:{ Count:2 }, ToString:function(args) { return `以${args[1]}为权重${args[0]}的动态移动平均`; } } ],
+ ["XMA", { Name:"XMA", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日偏移移动平均`; } } ],
+
+ ["RANGE", { Name:"RANGE", Param:{ Count:3 }, ToString:function(args) { return `${args[0]}位于${args[1]}和${args[2]}之间`; } } ],
+ ["CONST", { Name:"CONST", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的最后一日值`; } } ],
+ ["TOPRANGE", { Name:"TOPRANGE", Param:{ Count:1 }, ToString:function(args) { return `当前值是近${args[0]}周期的最大值`; } } ],
+ ["LOWRANGE", { Name:"LOWRANGE", Param:{ Count:1 }, ToString:function(args) { return `当前值是近${args[0]}周期的最小值`; } } ],
+ ["FINDHIGH", { Name:"FINDHIGH", Param:{ Count:4 }, ToString:function(args) { return `${args[0]}在${args[1]}日前的${args[2]}天内第${args[3]}个最高价`; } } ],
+ ["FINDHIGHBARS", { Name:"FINDHIGHBARS", Param:{ Count:4 }, ToString:function(args) { return `${args[0]}在${args[1]}日前的${args[2]}天内第${args[3]}个最高价到当前周期的周期数`; } } ],
+ ["FINDLOW", { Name:"FINDLOW", Param:{ Count:4 }, ToString:function(args) { return `${args[0]}在${args[1]}日前的${args[2]}天内第${args[3]}个最低价`; } } ],
+ ["FINDLOWBARS", { Name:"FINDLOWBARS", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}在${args[1]}日前的${args[2]}天内第${args[3]}个最低价到当前周期的周期数`; } } ],
+ ["SUM", { Name:"SUM", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}${args[1]}日累加`; } } ],
+ ["MULAR", { Name:"MULAR", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}和${args[1]}日累乘`; } } ],
+ ["AMA", { Name:"AMA", Param:{ Count:2 }, ToString:function(args) { return `以${args[1]}为权重${args[0]}的自适应均线`; } } ],
+ ["TMA", { Name:"TMA", Param:{ Count:3 }, ToString:function(args) { return `${args[0]}的${args[1]}日[${args[2]}日权重]移动平均`; } } ],
+ ["CROSS", { Name:"CROSS", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}上穿${args[1]}`; } } ],
+ ["LONGCROSS", { Name:"LONGCROSS", Param:{ Count:3 }, ToString:function(args) { return `${args[0]}小于${args[1]}保持${args[2]}个交易日后交叉上穿`; } } ],
+ ["UPNDAY", { Name:"UPNDAY", Param:{ Count:2 }, ToString:function(args) { return `最近${args[1]}日${args[0]}连涨`; } } ],
+ ["DOWNNDAY", { Name:"DOWNNDAY", Param:{ Count:2 }, ToString:function(args) { return `最近${args[1]}日${args[0]}连跌`; } } ],
+ ["NDAY", { Name:"NDAY", Param:{ Count:3 }, ToString:function(args) { return `最近${args[2]}日${args[0]}一直大于${args[1]}`; } } ],
+ ["EXIST", { Name:"EXIST", Param:{ Count:2 }, ToString:function(args) { return `最近${args[1]}日存在${args[0]}`; } } ],
+ ["EXISTR", { Name:"EXISTR", Param:{ Count:3 }, ToString:function(args) { return `从前${args[1]}日到前${args[2]}日存在${args[0]}`; } } ],
+ ["EVERY", { Name:"EVERY", Param:{ Count:2 }, ToString:function(args) { return `最近${args[1]}日一直存在${args[0]}`; } } ],
+ ["LAST", { Name:"LAST", Param:{ Count:3 }, ToString:function(args) { return `从前${args[1]}日到前${args[2]}日持续${args[0]}`; } } ],
+ ["NOT", { Name:"NOT", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}取反`; } } ],
+ ["IF", { Name:"IF", Param:{ Count:3 }, ToString:function(args) { return `如果${args[0]},返回${args[1]},否则返回${args[2]}`; } } ],
+ ["IFF", { Name:"IFF", Param:{ Count:3 }, ToString:function(args) { return `如果${args[0]},返回${args[1]},否则返回${args[2]}`; } } ],
+ ["IFN", { Name:"IFN", Param:{ Count:3 }, ToString:function(args) { return `如果${args[0]},返回${args[1]},否则返回${args[2]}`; } } ],
+
+ ["MAX", { Name:"MAX", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}和${args[1]}的较大值`; } } ],
+ ["MIN", { Name:"MIN", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}和${args[1]}的较小值`; } } ],
+ ["ACOS", { Name:"ACOS", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的反余弦`; } } ],
+ ["ASIN", { Name:"ASIN", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的反正弦`; } } ],
+ ["ATAN", { Name:"ATAN", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的反正切`; } } ],
+ ["COS", { Name:"COS", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的余弦`; } } ],
+ ["SIN", { Name:"SIN", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的正弦`; } } ],
+ ["TAN", { Name:"TAN", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的正切`; } } ],
+ ["EXP", { Name:"EXP", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的指数`; } } ],
+ ["LN", { Name:"LN", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的自然对数`; } } ],
+ ["LOG", { Name:"LOG", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的对数`; } } ],
+ ["SQRT", { Name:"SQRT", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的开方`; } } ],
+ ["ABS", { Name:"ABS", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的绝对值`; } } ],
+ ["POW", { Name:"POW", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}乘幂`; } } ],
+ ["CEILING", { Name:"CEILING", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的向上舍入`; } } ],
+ ["FLOOR", { Name:"FLOOR", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的向上舍入`; } } ],
+ ["INTPART", { Name:"INTPART", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的整数部分`; } } ],
+ ["BETWEEN", { Name:"BETWEEN", Param:{ Count:3 }, ToString:function(args) { return `${args[0]}位于${args[1]}和${args[2]}之间`; } } ],
+ ["FRACPART", { Name:"FRACPART", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的小数部分`; } } ],
+ ["ROUND", { Name:"ROUND", Param:{ Count:1 }, ToString:function(args) { return `对${args[0]}(进行)四舍五入`; } } ],
+ ["ROUND2", { Name:"ROUND2", Param:{ Count:2 }, ToString:function(args) { return `对${args[0]}(进行)四舍五入`; } } ],
+ ["SIGN", { Name:"SIGN", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的符号`; } } ],
+ ["MOD", { Name:"MOD", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}关于${args[1]}的模`; } } ],
+ ["RAND", { Name:"RAND", Param:{ Count:1 }, ToString:function(args) { return `随机正整数`; } } ],
+
+ ["AVEDEV", { Name:"AVEDEV", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日平均绝对偏差`; } } ],
+ ["DEVSQ", { Name:"DEVSQ", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日数据偏差平方和`; } } ],
+ ["FORCAST", { Name:"FORCAST", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日线性回归预测值`; } } ],
+ ["TSMA", { Name:"TSMA", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}在${args[1]}个周期内的时间序列三角移动平均`; } } ],
+ ["SLOPE", { Name:"SLOPE", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日线性回归斜率`; } } ],
+ ["STD", { Name:"STD", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日估算标准差`; } } ],
+ ["STDP", { Name:"STDP", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日总体标准差`; } } ],
+ ["STDDEV", { Name:"STDDEV", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日标准偏差`; } } ],
+ ["VAR", { Name:"VAR", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日估算样本方差`; } } ],
+ ["VARP", { Name:"VARP", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日总体样本方差`; } } ],
+ ["COVAR", { Name:"COVAR", Param:{ Count:3 }, ToString:function(args) { return `${args[0]}和${args[1]}的${args[2]}周期的协方差`; } } ],
+ ["RELATE", { Name:"RELATE", Param:{ Count:3 }, ToString:function(args) { return `${args[0]}和${args[1]}的${args[0]}周期的相关系数`; } } ],
+ ["BETA", { Name:"BETA", Param:{ Count:1 }, ToString:function(args) { return `β(Beta)系数`; } } ],
+ ["BETAEX", { Name:"BETAEX", Param:{ Count:3 }, ToString:function(args) { return `${args[0]}和${args[1]}的${args[2]}周期的相关放大系数`; } } ],
+
+ ["COST", { Name:"COST", Param:{ Count:1 }, ToString:function(args) { return `获利盘为${args[0]}%的成本分布`; } } ],
+ ["WINNER", { Name:"WINNER", Param:{ Count:1 }, ToString:function(args) { return `以${args[0]}计算的获利盘比例`; } } ],
+ ["LWINNER", { Name:"LWINNER", Param:{ Count:2 }, ToString:function(args) { return `最近${args[0]}日那部分成本以${args[1]}价格卖出的获利盘比例`; } } ],
+ ["PWINNER", { Name:"PWINNER", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}日前那部分成本以${args[1]}价格卖出的获利盘比例`; } } ],
+ ["COSTEX", { Name:"COSTEX", Param:{ Count:2 }, ToString:function(args) { return `位于价格${args[0]}和${args[1]}间的成本`; } } ],
+ ["PPART", { Name:"PPART", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}日前那部分成本占总成本的比例`; } } ],
+
+ ["SAR", { Name:"SAR", Param:{ Count:3 }, ToString:function(args) { return `步长为${args[1]}极限值为${args[0]}的${args[2]}日抛物转向`; } } ],
+ ["SARTURN", { Name:"SARTURN", Param:{ Count:3 }, ToString:function(args) { return `步长为${args[1]}极限值为${args[0]}的${args[2]}日抛物转向点`; } } ],
+
+ //字符串函数
+ ["CON2STR", { Name:"CON2STR", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}转为字符串`; } } ],
+ ["VAR2STR", { Name:"VAR2STR", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}转为字符串`; } } ],
+ ["STR2CON", { Name:"STR2CON", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}转为数字`; } } ],
+ ["STRLEN", { Name:"STRLEN", Param:{ Count:1 }, ToString:function(args) { return `得到${args[0]}字符串长度`; } } ],
+ ["STRCAT", { Name:"STRCAT", Param:{ Count:2 }, ToString:function(args) { return `字符串相加`; } } ],
+ ["VARCAT", { Name:"VARCAT", Param:{ Count:2 }, ToString:function(args) { return `字符串相加`; } } ],
+ ["STRSPACE", { Name:"STRSPACE", Param:{ Count:1 }, ToString:function(args) { return `字符串${args[0]}加一空格`; } } ],
+ ["SUBSTR", { Name:"SUBSTR", Param:{ Count:3 }, ToString:function(args) { return `字符串${args[0]}中取一部分`; } } ],
+ ["STRCMP", { Name:"STRCMP", Param:{ Count:2 }, ToString:function(args) { return `字符串${args[0]}和字符串${args[1]}比较`; } } ],
+ ["FINDSTR", { Name:"FINDSTR", Param:{ Count:2 }, ToString:function(args) { return `字符串${args[0]}中查找字符串${args[1]}`; } } ],
+ ["NAMEINCLUD", { Name:"NAMEINCLUD", Param:{ Count:1 }, ToString:function(args) { return `查找品种名称中包含${args[0]}`; } } ],
+ ["CODELIKE", { Name:"CODELIKE", Param:{ Count:1 }, ToString:function(args) { return `查找品种名称中包含${args[0]}`; } } ],
+ ["INBLOCK", { Name:"AVEDEV", Param:{ Count:1 }, ToString:function(args) { return `属于${args[0]}板块`; } } ],
+
+
+ [
+ "HHVBARS",
+ {
+ Name:"HHVBARS", Param:{ Count:2 },
+ ToString:function(args)
+ {
+ if (args[1]==0) return `历史${args[0]}新高距今天数`;
+ return `${args[1]}日内${args[0]}新高距今天数`;
+ }
+ }
+ ],
+
+ [
+ "LLVBARS",
+ {
+ Name:"LLVBARS", Param:{ Count:2 },
+ ToString:function(args)
+ {
+ if (args[1]==0) return `历史${args[0]}新低距今天数`;
+ return `${args[1]}日内${args[0]}新低距今天数`;
+ }
+ }
+ ]
+ ]
+ );
+
+ this.CallFunctionExplain=function(funcName, args, node)
+ {
+ if (this.FUNCTION_INFO_LIST.has(funcName))
+ {
+ var item=this.FUNCTION_INFO_LIST.get(funcName);
+ if (item.Param.Count!=args.length)
+ this.ThrowUnexpectedNode(node,`函数${funcName}参数个数不正确. 需要${item.Param.Count}个参数`);
+ return item.ToString(args);
+ }
+
+ switch(funcName)
+ {
+ case "CALCSTOCKINDEX":
+ return `引用${args[0]}的${args[1]}指标第${args[2]}个输出值`;
+
+ case "PEAK":
+ case "PEAKBARS":
+ case "ZIG":
+ case "ZIGA":
+ case "TROUGH":
+ case "TROUGHBARS":
+ return this.GetZIGExplain(funcName,args);
+
+ case "FINANCE":
+ return this.GetFinanceExplain(args);
+ case "DYNAINFO":
+ return this.GetDynainfoExplain(args);
+
+ case 'CLOSE':
+ case 'C':
+ case 'VOL':
+ case 'V':
+ case 'OPEN':
+ case 'O':
+ case 'HIGH':
+ case 'H':
+ case 'LOW':
+ case 'L':
+ case 'AMOUNT':
+ case 'AMO':
+ return this.GetOtherSymbolExplain( {FunctionName:funcName, Args:args} ,node);
+
+ //绘图函数
+ case "PLOYLINE":
+ return `当满足条件${args[0]}时以${args[1]}位置为顶点画折线连接`;
+ case "DRAWLINE":
+ return `当满足条件${args[0]}时,在${args[1]}位置画直线起点,当满足条件${args[2]}时,在${args[3]}位置画直线终点,${args[4]}表示是否延长`;
+ case "DRAWSL":
+ return `当满足条件${args[0]}时,在${args[1]}位置画斜线线性回归,${args[2]}斜率,${args[3]}长度,${args[4]}方向`;
+ case "DRAWKLINE":
+ return 'K线';
+ case "DRAWICON":
+ return `当满足条件${args[0]}时,在${args[1]}位置画${args[2]}号图标`;
+ case "DRAWTEXT":
+ return `当满足条件${args[0]}时,在${args[1]}位置书写文字`;
+ case "DRAWTEXT_FIX":
+ return `当满足条件${args[0]}时,在横轴${args[1]}纵轴${args[2]}位置书写文字`;
+ case "DRAWNUMBER":
+ return `当满足条件${args[0]}时,在${args[1]}位置书写数字`;
+ case "DRAWNUMBER_FIX":
+ return `当满足条件${args[0]}时,在横轴${args[1]}纵轴${args[2]}位置书写数字`;
+ case "RGB":
+ return `自定色[${args[0]},${args[1]},${args[2]}]`;
+ case "DRAWBAND":
+ return '画带状线';
+ case "DRAWRECTREL":
+ return "相对位置上画矩形.";
+ case "DRAWGBK":
+ return "填充背景";
+ case "STICKLINE":
+ var barType="";
+ if (args[4]==-1) barType="虚线空心柱";
+ else if (args[4]==0) barType="实心柱";
+ else barType="实线空心柱";
+ return `当满足条件${args[0]}时, 在${args[1]}和${args[2]}位置之间画柱状线,宽度为${args[3]},${barType}`;
+
+ default:
+ this.ThrowUnexpectedNode(node,`函数${funcName}不存在`);
+ }
+ }
+
+ this.GetDynainfoExplain=function(args)
+ {
+ const DATA_NAME_MAP=new Map(
+ [
+ [3,"前收盘价"], [4,"开盘价"], [5,"最高价"], [6,"最低价"], [7,"现价"], [8,'总量'], [9,"现量"],
+ [10,"总金额"], [11,"均价"], [12,"日涨跌"], [13,"振幅"], [14,"涨幅"], [15,"开盘时的成交金额"],
+ [16,"前5日每分钟均量"], [17,"量比"], [18,"上涨家数"], [19,"下跌家数"]
+ ]);
+
+ var id=args[0];
+ if (DATA_NAME_MAP.has(id)) return DATA_NAME_MAP.get(id);
+
+ return `即时行情[${id}]`;
+ }
+
+ this.GetFinanceExplain=function(args)
+ {
+ const DATA_NAME_MAP=new Map(
+ [
+ [1,"总股本"], [2,"市场类型"], [3,"沪深品种类型"], [4,"沪深行业代码"], [5,"B股"], [6,"H股"], [7,"流通股本[股]"], [8,"股东人数[户]"], [9,"资产负债率%"],
+ [10,"总资产"], [11,"流动资产"], [12,"固定资产"], [13,"无形资产"], [15,"流动负债"], [16,"少数股东权益"]
+
+ ]);
+ var id=args[0];
+
+ if (DATA_NAME_MAP.has(id)) return DATA_NAME_MAP.get(id);
+
+ return `财务数据[${id}]`;
+ }
+
+ this.GetZIGExplain=function(funcName,args)
+ {
+ var value=args[0];
+ if (value==0) value="开盘价";
+ else if (value==1) value="最高价";
+ else if (value==2) value="最低价";
+ else if (value==3) value="收盘价";
+
+ switch(funcName)
+ {
+ case "PEAK":
+ return `${value}的${args[1]}%之字转向的前${args[2]}个波峰值`;
+ case "PEAKBARS":
+ return `${value}的${args[1]}5%之字转向的前${args[2]}个波峰位置`;
+ case "ZIG":
+ return `${value}的${args[1]}的之字转向`;
+ case "ZIGA":
+ return `${value}变化${args[1]}的之字转向`;
+ case "TROUGH":
+ return `${value}的${args[1]}%之字转向的前${args[2]}个波谷值`;
+ case "TROUGHBARS":
+ return `${value}的${args[1]}%之字转向的前${args[2]}个波谷位置`;
+ }
+ }
+
+ this.GetColorExplain=function(colorName)
+ {
+ const COLOR_MAP=new Map(
+ [
+ ['COLORBLACK','黑色'],['COLORBLUE','蓝色'],['COLORGREEN','绿色'],['COLORCYAN','青色'],['COLORRED','红色'],
+ ['COLORMAGENTA','洋红色'],['COLORBROWN','棕色'],['COLORLIGRAY','淡灰色'],['COLORGRAY','深灰色'],['COLORLIBLUE','淡蓝色'],
+ ['COLORLIGREEN','淡绿色'],['COLORLICYAN','淡青色'],['COLORLIRED','淡红色'],['COLORLIMAGENTA','淡洋红色'],['COLORWHITE','白色'],['COLORYELLOW','黄色']
+ ]);
+
+ if (COLOR_MAP.has(colorName)) return COLOR_MAP.get(colorName);
+
+ //COLOR 自定义色
+ //格式为COLOR+“RRGGBB”:RR、GG、BB表示红色、绿色和蓝色的分量,每种颜色的取值范围是00-FF,采用了16进制。
+ //例如:MA5:MA(CLOSE,5),COLOR00FFFF 表示纯红色与纯绿色的混合色:COLOR808000表示淡蓝色和淡绿色的混合色。
+ if (colorName.indexOf('COLOR')==0) return '#'+colorName.substr(5);
+
+ return 'rgb(30,144,255)';
+ }
+
+ this.GetLineWidthExplain=function(lineWidth)
+ {
+ var width=parseInt(lineWidth.replace("LINETHICK",""));
+ if (IFrameSplitOperator.IsPlusNumber(width)) return width;
+ return 1;
+ }
+
+ this.SymbolPeriodExplain=function(valueName,period)
+ {
+ const mapStockDataName=new Map(
+ [
+ ['CLOSE',"收盘价"],["C","收盘价"],['VOL',"成交量"],['V',"成交量"], ['OPEN',"开盘价"], ['O',"开盘价"],
+ ['HIGH',"最高价"],['H',"最高价"], ['LOW',"最低价"],['L',"最低价"],['AMOUNT',"成交金额"],['AMO',"成交金额"],
+ ['VOLINSTK',"持仓量"]
+ ]);
+ //MIN1,MIN5,MIN15,MIN30,MIN60,DAY,WEEK,MONTH,SEASON,YEAR
+ const mapPeriodName=new Map(
+ [
+ ["MIN1","1分钟"], ["MIN5", "5分钟"], ["MIN15", "15分钟"], ["MIN30","30分钟"],["MIN60","60分钟"],
+ ["DAY","日"],["WEEK","周"], ["MONTH", "月"], ['SEASON',"季"], ["YEAR", "年"],["WEEK2","双周"], ["HALFYEAR", "半年"]
+ ]);
+
+ var dataName=valueName;
+ if (mapStockDataName.has(valueName)) dataName=mapStockDataName.get(valueName);
+
+ var periodName=period;
+ if (mapPeriodName.has(period)) periodName=mapPeriodName.get(period);
+
+ return `${dataName}[取${periodName}数据]`;
+ }
+
+ this.GetOtherSymbolExplain=function(obj, node)
+ {
+ const mapStockDataName=new Map(
+ [
+ ['CLOSE',"收盘价"],["C","收盘价"],['VOL',"成交量"],['V',"成交量"], ['OPEN',"开盘价"], ['O',"开盘价"],
+ ['HIGH',"最高价"],['H',"最高价"], ['LOW',"最低价"],['L',"最低价"],['AMOUNT',"成交金额"],['AMO',"成交金额"],
+ ['VOLINSTK',"持仓量"]
+ ]);
+
+ if (obj.FunctionName)
+ {
+ var args=obj.Args;
+ var dataName=mapStockDataName.get(obj.FunctionName);
+ return `[${args[0]}]${dataName}`;
+ }
+ else if (obj.Literal)
+ {
+ var value=obj.Literal.toUpperCase();
+ var args=value.split("$");
+ if (!mapStockDataName.has(args[1])) return "";
+ var symbol=args[0];
+ var dataName=mapStockDataName.get(args[1]);
+ return `[${symbol}]${dataName}`;
+ }
+ }
+
+ this.IsDrawFunction=function(name)
+ {
+ let setFunctionName=new Set(
+ [
+ "STICKLINE","DRAWTEXT",'SUPERDRAWTEXT','DRAWLINE','DRAWBAND','DRAWKLINE','DRAWKLINE_IF','PLOYLINE',
+ 'POLYLINE','DRAWNUMBER',"DRAWNUMBER_FIX",'DRAWICON','DRAWCHANNEL','PARTLINE','DRAWTEXT_FIX','DRAWGBK','DRAWTEXT_LINE','DRAWRECTREL',"DRAWTEXTABS",
+ 'DRAWOVERLAYLINE',"FILLRGN", "FILLRGN2","FILLTOPRGN", "FILLBOTTOMRGN", "FILLVERTICALRGN","FLOATRGN","DRAWSL", "DRAWGBK2"
+ ]);
+ if (setFunctionName.has(name)) return true;
+
+ return false;
+ }
+
+ //赋值
+ this.VisitAssignmentExpression=function(node)
+ {
+ let left=node.Left;
+ if (left.Type!=Syntax.Identifier) this.ThrowUnexpectedNode(node);
+
+ let varName=left.Name;
+
+ let right=node.Right;
+ let value=null;
+ if (right.Type==Syntax.BinaryExpression || right.Type==Syntax.LogicalExpression)
+ value=this.VisitBinaryExpression(right);
+ else if (right.Type==Syntax.CallExpression)
+ value=this.VisitCallExpression(right);
+ else if (right.Type==Syntax.Literal)
+ {
+ value=right.Value;
+ if (IFrameSplitOperator.IsString(value) && right.Value.indexOf("$")>0)
+ value=this.GetOtherSymbolExplain({ Literal:value }, node);
+ }
+ else if (right.Type==Syntax.Identifier) //右值是变量
+ value=this.ReadVariable(right.Name,right);
+ else if (right.Type==Syntax.MemberExpression)
+ value=this.ReadMemberVariable(right);
+ else if (right.Type==Syntax.UnaryExpression)
+ {
+ if (right.Operator=='-')
+ {
+ var tempValue=this.GetNodeValue(right.Argument);
+ value='-'+tempValue;
+ }
+ else
+ {
+ value=right.Argument.Value;
+ }
+ }
+
+ JSConsole.Complier.Log('[JSExplainer::VisitAssignmentExpression]' , varName, ' = ',value);
+ this.VarTable.set(varName,value);
+ }
+
+ //逻辑运算
+ this.VisitBinaryExpression=function(node)
+ {
+ let stack=[];
+ stack.push(node);
+ let temp=null;
+
+ while(stack.length!=0)
+ {
+ temp=stack[stack.length-1];
+ if (temp.Left && node!=temp.Left && node!=temp.Right)
+ {
+ stack.push(temp.Left);
+ }
+ else if (temp.Right && node!=temp.Right)
+ {
+ stack.push(temp.Right);
+ }
+ else
+ {
+ let value=stack.pop();
+ if (value.Type==Syntax.BinaryExpression) //只遍历操作符就可以
+ {
+ let leftValue=this.GetNodeValue(value.Left);
+ let rightValue=this.GetNodeValue(value.Right);
+
+ JSConsole.Complier.Log('[JSExplainer::VisitBinaryExpression] BinaryExpression',value , leftValue, rightValue);
+ value.Out=null; //保存中间值
+
+ value.Out=`(${leftValue} ${value.Operator} ${rightValue})`;
+ if (leftValue=="收盘价" && rightValue=="开盘价")
+ {
+ if (value.Operator==">") value.Out='(收阳线)';
+ else if (value.Operator=="<") value.Out='(收阴线)';
+ else if (value.Operator=="=") value.Out='(平盘)';
+ }
+ else if (leftValue=="开盘价" && rightValue=="收盘价")
+ {
+ if (value.Operator=="<") value.Out='(收阳线)';
+ else if (value.Operator==">") value.Out='(收阴线)';
+ else if (value.Operator=="=") value.Out='(平盘)';
+ }
+
+ JSConsole.Complier.Log('[JSExplainer::VisitBinaryExpression] BinaryExpression',value);
+ }
+ else if (value.Type==Syntax.LogicalExpression)
+ {
+ let leftValue=this.GetNodeValue(value.Left);
+ let rightValue=this.GetNodeValue(value.Right);
+
+ JSConsole.Complier.Log('[JSExecute::VisitBinaryExpression] LogicalExpression',value , leftValue, rightValue);
+ value.Out=null; //保存中间值
+
+ switch(value.Operator)
+ {
+ case '&&':
+ case 'AND':
+ value.Out=`(${leftValue} 并且 ${rightValue})`;
+ break;
+ case '||':
+ case 'OR':
+ value.Out=`(${leftValue} 或者 ${rightValue})`;
+ break;
+ }
+
+ JSConsole.Complier.Log('[JSExplainer::VisitBinaryExpression] LogicalExpression',value);
+ }
+
+ node=temp;
+ }
+ }
+
+ return node.Out;
+
+ }
+
+ this.GetNodeValue=function(node)
+ {
+ switch(node.Type)
+ {
+ case Syntax.Literal: //数字
+ return node.Value;
+ case Syntax.UnaryExpression:
+ if (node.Operator=='-')
+ {
+ let value=this.GetNodeValue(node.Argument);
+ return '-'+value;
+ }
+ return node.Argument.Value;
+ case Syntax.Identifier:
+ let value=this.ReadVariable(node.Name,node);
+ return value;
+ case Syntax.BinaryExpression:
+ case Syntax.LogicalExpression:
+ return node.Out;
+ case Syntax.CallExpression:
+ return this.VisitCallExpression(node);
+ default:
+ this.ThrowUnexpectedNode(node);
+ }
+ }
+
+ //读取变量
+ this.ReadVariable=function(name,node)
+ {
+ if (this.ConstVarTable.has(name))
+ {
+ let data=this.ConstVarTable.get(name);
+ return data;
+ }
+
+ if (g_JSComplierResource.IsCustomVariant(name)) return this.ReadCustomVariant(name,node); //读取自定义变量
+
+ if (this.VarTable.has(name)) return this.VarTable.get(name);
+
+ if (name.indexOf('#')>0)
+ {
+ var aryPeriod=name.split('#');
+ return this.SymbolPeriodExplain(aryPeriod[0],aryPeriod[1]);
+ }
+
+ this.ThrowUnexpectedNode(node, '变量'+name+'不存在');
+ return name;
+ }
+
+ this.ThrowUnexpectedNode=function(node,message)
+ {
+ let marker=node.Marker;
+ let msg=message || "执行异常";
+
+ return this.ErrorHandler.ThrowError(marker.Index,marker.Line,marker.Column,msg);
+
+ }
+
+ this.ThrowError=function()
+ {
+
+ }
+}
+
+
+JSComplier.Explain=function(code,option, errorCallback)
+{
+ //异步调用
+ //var asyncExecute= async function() es5不能执行 去掉异步
+ var asyncExplain= function()
+ {
+ try
+ {
+ JSConsole.Complier.Log('[JSComplier.Explain]',code,option);
+
+ JSConsole.Complier.Log('[JSComplier.Explain] parser .....');
+ let parser=new JSParser(code);
+ parser.Initialize();
+ let program=parser.ParseScript();
+
+ let ast=program;
+ JSConsole.Complier.Log('[JSComplier.Explain] parser finish.', ast);
+
+ JSConsole.Complier.Log('[JSComplier.Explain] explain .....');
+ let execute=new JSExplainer(ast,option);
+ execute.ErrorCallback=errorCallback; //执行错误回调
+ execute.JobList=parser.Node.GetDataJobList();
+ execute.JobList.push({ID:JS_EXECUTE_JOB_ID.JOB_RUN_SCRIPT});
+ let result=execute.Run();
+
+ }catch(error)
+ {
+ JSConsole.Complier.Log(error);
+
+ if (errorCallback) errorCallback(error, option.CallbackParam);
+ }
+ }
+
+ asyncExplain();
+
+ JSConsole.Complier.Log('[JSComplier.Explain] async explain.');
+}
\ No newline at end of file
diff --git a/uni_modules/jones-hqchart2/js_sdk/umychart.extendchart.wechat.js b/uni_modules/jones-hqchart2/js_sdk/umychart.extendchart.wechat.js
new file mode 100644
index 0000000..09df6bf
--- /dev/null
+++ b/uni_modules/jones-hqchart2/js_sdk/umychart.extendchart.wechat.js
@@ -0,0 +1,1003 @@
+/*
+ copyright (c) 2018 jones
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ 开源项目 https://github.com/jones2000/HQChart
+
+ jones_2000@163.com
+
+ 图形扩展画法
+*/
+//日志
+import { JSConsole } from "./umychart.console.wechat.js"
+
+//行情数据结构体 及涉及到的行情算法(复权,周期等)
+import
+{
+ JSCommon_ChartData as ChartData, JSCommon_HistoryData as HistoryData,
+ JSCommon_SingleData as SingleData, JSCommon_MinuteData as MinuteData,
+ JSCommon_Guid as Guid,
+ JSCommon_ToFixedPoint as ToFixedPoint,
+ JSCommon_ToFixedRect as ToFixedRect,
+} from "./umychart.data.wechat.js";
+
+import
+{
+ JSCommonCoordinateData as JSCommonCoordinateData,
+ JSCommonCoordinateData_MARKET_SUFFIX_NAME as MARKET_SUFFIX_NAME
+} from "./umychart.coordinatedata.wechat.js";
+
+import
+{
+ JSCommonResource_Global_JSChartResource as g_JSChartResource,
+ JSCommonResource_JSCHART_LANGUAGE_ID as JSCHART_LANGUAGE_ID,
+ JSCommonResource_Global_JSChartLocalization as g_JSChartLocalization,
+} from './umychart.resource.wechat.js'
+
+import
+{
+ JSCommonSplit_IFrameSplitOperator as IFrameSplitOperator,
+} from './umychart.framesplit.wechat.js'
+
+function IExtendChartPainting()
+{
+ this.Canvas; //画布
+ this.ChartBorder; //边框信息
+ this.ChartFrame; //框架画法
+ this.Name; //名称
+ this.Data; // = new ChartData(); //数据区
+ this.ClassName = 'IExtendChartPainting';
+ this.IsDynamic = false;
+ this.IsEraseBG = false; //是否每次画的时候需要擦除K线图背景
+ this.IsAnimation=false;
+ this.DrawAfterTitle = false; //是否在动态标题画完以后再画,防止动态标题覆盖
+
+ //上下左右间距
+ this.Left = 5;
+ this.Right = 5;
+ this.Top = 5;
+ this.Bottom = 5;
+
+ this.Draw = function () { } //画图接口
+ this.SetOption = function (option) { } //设置参数接口
+}
+
+//K线Tooltip, 显示在左边或右边
+function KLineTooltipPaint()
+{
+ this.newMethod = IExtendChartPainting; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.IsDynamic = true;
+ this.IsEraseBG = true;
+ this.DrawAfterTitle = true;
+ this.ClassName = 'KLineTooltipPaint';
+ this.LatestPoint; //手势位置
+ this.ShowPosition=0; //显示位置 0=左 1=右
+
+ this.BorderColor = g_JSChartResource.TooltipPaint.BorderColor; //边框颜色
+ this.BGColor = g_JSChartResource.TooltipPaint.BGColor; //背景色
+ this.TitleColor = g_JSChartResource.TooltipPaint.TitleColor; //标题颜色
+ this.Font = [g_JSChartResource.TooltipPaint.TitleFont];
+
+ this.Width = 50;
+ this.Height = 100;
+ this.LineHeight = 15; //行高
+
+ this.Left = 1;
+ this.Top = 0;
+
+ this.HQChart;
+ this.KLineTitlePaint;
+ this.IsHScreen = false; //是否横屏
+ this.LanguageID = JSCHART_LANGUAGE_ID.LANGUAGE_CHINESE_ID;
+
+ this.GetLeft = function ()
+ {
+ if (this.IsHScreen)
+ {
+ return this.ChartBorder.GetRightEx()-this.Height-this.Top;
+ }
+ else
+ {
+ if (this.ShowPosition==0)
+ return this.ChartBorder.GetLeft()+this.Left;
+ else
+ return this.ChartBorder.GetRight()-this.Width-this.Left;
+ }
+ }
+
+ this.GetTop = function ()
+ {
+ if (this.IsHScreen)
+ {
+ if (this.ShowPosition==0)
+ return this.ChartBorder.GetTop()+this.Left;
+ else
+ return this.ChartBorder.GetBottom()-this.Width-this.Left;
+ }
+ else
+ {
+ return this.ChartBorder.GetTopEx()+this.Top;
+ }
+ }
+
+ this.Draw = function ()
+ {
+ if (!this.HQChart || !this.HQChart.TitlePaint || !this.HQChart.TitlePaint[0]) return;
+ if (!this.HQChart.IsOnTouch) return;
+
+ this.KLineTitlePaint = this.HQChart.TitlePaint[0];
+ var klineData = this.KLineTitlePaint.GetCurrentKLineData();
+ if (!klineData) return;
+
+ var upperSymbol;
+ if (this.HQChart.Symbol) upperSymbol = this.HQChart.Symbol.toUpperCase();
+ var isFutures=MARKET_SUFFIX_NAME.IsChinaFutures(upperSymbol)?true:false;
+
+ var lineCount = 8; //显示函数
+ if (this.ClassName === 'MinuteTooltipPaint')
+ {
+ lineCount=7;
+ if (isFutures && IFrameSplitOperator.IsNumber(klineData.Position)) ++lineCount; //期货多一个持仓量
+ }
+ else
+ {
+ if (IFrameSplitOperator.IsNumber(klineData.Time)) ++lineCount; //分钟K线多一列时间
+ if (isFutures && IFrameSplitOperator.IsNumber(klineData.Position)) ++lineCount; //持仓量
+ }
+
+ this.IsHScreen = this.ChartFrame.IsHScreen === true;
+ this.Canvas.font = this.Font[0];
+ var defaultfloatPrecision = JSCommonCoordinateData.GetfloatPrecision(this.HQChart.Symbol);//价格小数位数
+ var maxText = ' 擎: 9999.99亿 ';
+ if (defaultfloatPrecision >= 5) maxText = ` 擎: ${99.99.toFixed(defaultfloatPrecision)} `; //小数位数太多了
+ this.Width = this.Canvas.measureText(maxText).width;
+ this.Height = this.LineHeight * lineCount + 2 * 2;
+ if (klineData && klineData.High>0)
+ {
+ maxText=` 擎: ${klineData.High.toFixed(defaultfloatPrecision)} `;
+ var textWidth=this.Canvas.measureText(maxText).width;
+ if (textWidth>this.Width) this.Width=textWidth;
+ }
+
+ this.CalculateShowPosition();
+ this.DrawBG();
+ this.DrawTooltipData(klineData);
+ this.DrawBorder();
+ }
+
+ //判断显示位置
+ this.CalculateShowPosition=function()
+ {
+ this.ShowPosition=0;
+ if (!this.LatestPoint) return;
+
+ if(this.IsHScreen)
+ {
+ var top=this.ChartBorder.GetTop();
+ var height=this.ChartBorder.GetHeight();
+ var yCenter=top+height/2;
+ if (this.LatestPoint.Y0)
+ {
+ var value = (item.Close - item.YClose) / item.YClose * 100;
+ var color = this.KLineTitlePaint.GetColor(value, 0);
+ var text = value.toFixed(2) + '%';
+ }
+ else
+ {
+ var text='--.--';
+ var color = this.KLineTitlePaint.GetColor(0, 0);
+ }
+ this.Canvas.fillStyle = color;
+ this.Canvas.fillText(text, left + labelWidth, top);
+
+ this.Canvas.fillStyle = this.TitleColor;
+
+ if (IFrameSplitOperator.IsNumber(item.Vol))
+ {
+ top += this.LineHeight;
+ text = g_JSChartLocalization.GetText('Tooltip-Vol', this.LanguageID);
+ this.Canvas.fillText(text, left, top);
+ var text = this.HQChart.FormatValueString(item.Vol, 2, this.LanguageID);
+ this.Canvas.fillText(text, left + labelWidth, top);
+ }
+
+ if (IFrameSplitOperator.IsNumber(item.Amount))
+ {
+ top += this.LineHeight;
+ text = g_JSChartLocalization.GetText('Tooltip-Amount',this.LanguageID);
+ this.Canvas.fillText(text, left, top);
+ var text = this.HQChart.FormatValueString(item.Amount, 2, this.LanguageID);
+ this.Canvas.fillText(text, left + labelWidth, top);
+ }
+
+ //持仓量
+ var upperSymbol;
+ if (this.HQChart.Symbol) upperSymbol = this.HQChart.Symbol.toUpperCase();
+ if (MARKET_SUFFIX_NAME.IsChinaFutures(upperSymbol) && IFrameSplitOperator.IsNumber(item.Position))
+ {
+ this.Canvas.fillStyle = this.TitleColor;
+ top += this.LineHeight;
+ text = g_JSChartLocalization.GetText('Tooltip-Position', this.LanguageID);
+ this.Canvas.fillText(text, left, top);
+ var text = IFrameSplitOperator.FormatValueString(item.Position, 2, this.LanguageID);
+ this.Canvas.fillText(text, left + labelWidth, top);
+ }
+
+ if (this.IsHScreen) this.Canvas.restore();
+ }
+
+ //设置参数接口
+ this.SetOption = function (option)
+ {
+ if (option.LineHeight > 0) this.LineHeight = option.LineHeight;
+ if (option.BGColor) this.BGColor = option.BGColor;
+ if (option.LanguageID > 0) this.LanguageID = option.LanguageID;
+ }
+}
+
+function MinuteTooltipPaint()
+{
+ this.newMethod = KLineTooltipPaint; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.ClassName = 'MinuteTooltipPaint';
+ this.IsShowAveragePrice=true;
+
+ this.GetTop=function()
+ {
+ if (this.IsHScreen)
+ {
+ if (this.ShowPosition==0)
+ return this.ChartBorder.GetTop()+this.Left;
+ else
+ return this.ChartBorder.GetBottom()-this.Width-this.Left;
+ }
+ else
+ {
+ return this.ChartBorder.GetTop()+this.Top;
+ }
+ }
+
+ this.GetLeft=function()
+ {
+ if (this.IsHScreen)
+ {
+ return this.ChartBorder.GetRight()-this.Height-this.Top;
+ }
+ else
+ {
+ if (this.ShowPosition==0)
+ return this.ChartBorder.GetLeft()+this.Left;
+ else
+ return this.ChartBorder.GetRight()-this.Width-this.Left;
+ }
+ }
+
+ this.DrawTooltipData = function (item)
+ {
+ //console.log('[KLineTooltipPaint::DrawKLineData] ', item);
+ var defaultfloatPrecision = JSCommonCoordinateData.GetfloatPrecision(this.HQChart.Symbol);//价格小数位数
+ var left = this.GetLeft() + 2;
+ var top = this.GetTop() + 3;
+ this.YClose = this.KLineTitlePaint.YClose;
+
+ if (this.IsHScreen)
+ {
+ this.Canvas.save();
+ var x = this.GetLeft() + this.Height, y = this.GetTop();
+
+ this.Canvas.translate(x, y);
+ this.Canvas.rotate(90 * Math.PI / 180);
+
+ //x, y 作为原点
+ left = 2;
+ top = 3;
+ }
+
+ this.Canvas.textBaseline = "top";
+ this.Canvas.textAlign = "left";
+ this.Canvas.font = this.Font[0];
+ var labelWidth = this.Canvas.measureText('擎: ').width;
+
+ var aryDateTime = item.DateTime.split(' ');
+ if (aryDateTime && aryDateTime.length == 2)
+ {
+ var text = this.HQChart.FormatDateString(aryDateTime[0]);
+ this.Canvas.fillStyle = this.TitleColor;
+ this.Canvas.fillText(text, left, top);
+
+ top += this.LineHeight;
+ text = this.HQChart.FormatTimeString(aryDateTime[1]);
+ this.Canvas.fillText(text, left, top);
+ }
+
+ top += this.LineHeight;
+ this.Canvas.fillStyle = this.TitleColor;
+ text = g_JSChartLocalization.GetText('Tooltip-Price', this.LanguageID);
+ this.Canvas.fillText(text, left, top);
+ var color = this.KLineTitlePaint.GetColor(item.Close, this.YClose);
+ text = item.Close.toFixed(defaultfloatPrecision);
+ this.Canvas.fillStyle = color;
+ this.Canvas.fillText(text, left + labelWidth, top);
+
+ if (IFrameSplitOperator.IsNumber(item.AvPrice) && this.IsShowAveragePrice==true)
+ {
+ top += this.LineHeight;
+ this.Canvas.fillStyle = this.TitleColor;
+ text = g_JSChartLocalization.GetText('Tooltip-AvPrice', this.LanguageID);
+ this.Canvas.fillText(text, left, top);
+ var color = this.KLineTitlePaint.GetColor(item.AvPrice, this.YClose);
+ var text = item.AvPrice.toFixed(defaultfloatPrecision);
+ this.Canvas.fillStyle = color;
+ this.Canvas.fillText(text, left + labelWidth, top);
+ }
+
+ top += this.LineHeight;
+ this.Canvas.fillStyle = this.TitleColor;
+ text = g_JSChartLocalization.GetText('Tooltip-Increase', this.LanguageID);
+ this.Canvas.fillText(text, left, top);
+ var value = (item.Close - this.YClose) / this.YClose * 100;
+ var color = this.KLineTitlePaint.GetColor(value, 0);
+ var text = value.toFixed(2) + '%';
+ this.Canvas.fillStyle = color;
+ this.Canvas.fillText(text, left + labelWidth, top);
+
+ if (IFrameSplitOperator.IsNumber(item.Vol))
+ {
+ this.Canvas.fillStyle = this.TitleColor;
+ top += this.LineHeight;
+ text = g_JSChartLocalization.GetText('Tooltip-Vol', this.LanguageID);
+ this.Canvas.fillText(text, left, top);
+ var text = this.HQChart.FormatValueString(item.Vol, 2, this.LanguageID);
+ this.Canvas.fillText(text, left + labelWidth, top);
+ }
+
+ if (IFrameSplitOperator.IsNumber(item.Amount))
+ {
+ top += this.LineHeight;
+ text = g_JSChartLocalization.GetText('Tooltip-Amount', this.LanguageID);
+ this.Canvas.fillText(text, left, top);
+ var text = this.HQChart.FormatValueString(item.Amount, 2, this.LanguageID);
+ this.Canvas.fillText(text, left + labelWidth, top);
+ }
+
+ //持仓量
+ var upperSymbol;
+ if (this.HQChart.Symbol) upperSymbol = this.HQChart.Symbol.toUpperCase();
+ if (MARKET_SUFFIX_NAME.IsChinaFutures(upperSymbol) && IFrameSplitOperator.IsNumber(item.Position))
+ {
+ this.Canvas.fillStyle = this.TitleColor;
+ top += this.LineHeight;
+ text = g_JSChartLocalization.GetText('Tooltip-Position', this.LanguageID);
+ this.Canvas.fillText(text, left, top);
+ var text = IFrameSplitOperator.FormatValueString(item.Position, 2, this.LanguageID);
+ this.Canvas.fillText(text, left + labelWidth, top);
+ }
+
+
+ if (this.IsHScreen) this.Canvas.restore();
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+// 弹幕
+//弹幕数据 { X:X偏移, Y:Y偏移, Text:内容, Color:颜色 }
+function BarrageList()
+{
+ this.PlayList = []; //正在播放队列
+ this.Cache = []; //没有播放的弹幕数据
+ this.MinLineHeight = 40;
+ this.Height; //高度
+ this.Step = 1;
+
+ //{Canves:画布, Right:右边坐标, Left:左边坐标, Font:默认字体 }
+ this.GetPlayList = function (obj)
+ {
+ var canves = obj.Canves;
+ var right = obj.Right;
+ var left = obj.Left;
+ var width = right - left;
+ var isMoveStep = obj.IsMoveStep;
+
+ var list = [];
+ var yOffset = 0;
+ for (var i = 0; i < this.PlayList.length; ++i)
+ {
+ var ary = this.PlayList[i];
+ var lineHeight = this.MinLineHeight;
+ if (ary.Height > this.MinLineHeight) lineHeight = ary.Height;
+
+ var bAddNewItem = true; //是否需要加入新弹幕
+ var bRemoveFirst = false; //是否删除第1个数据
+ for (var j = 0; j < ary.Data.length; ++j)
+ {
+ var item = ary.Data[j];
+ var playItem = { X: item.X, Y: yOffset, Text: item.Text, Color: item.Color, Height: lineHeight, Font: item.Font, Info: item.Info };
+ list.push(playItem);
+
+ if (!isMoveStep) continue;
+
+ if (j == ary.Data.length - 1 && this.Cache.length > 0) //最后一个数据了 判断是否需要增加弹幕
+ {
+ bAddNewItem = false;
+ if (!item.TextWidth)
+ {
+ if (item.Font && item.Font.Name) canves.font = item.Font.Name;
+ else canves.font = obj.Font;
+ item.TextWidth = canves.measureText(playItem.Text + '擎擎').width;
+ }
+
+ if (item.X >= item.TextWidth)
+ bAddNewItem = true;
+ }
+ else if (j == 0)
+ {
+ bRemoveFirst = false;
+ if (!item.TextWidth)
+ {
+ if (item.Font && item.Font.Name) canves.font = item.Font.Name;
+ else canves.font = obj.Font;
+ item.TextWidth = canves.measureText(playItem.Text + '擎擎').width;
+ }
+
+ if (item.X > width + item.TextWidth) bRemoveFirst = true;
+ }
+
+ item.X += this.Step;
+ }
+
+ if (isMoveStep && bAddNewItem && this.Cache.length > 0) //最后一个数据了 判断是否需要增加弹幕
+ {
+ var cacheItem = this.Cache.shift();
+ var newItem = { X: 0, Text: cacheItem.Text, Color: cacheItem.Color, Font: cacheItem.Font, Info: cacheItem.Info };
+ ary.Data.push(newItem);
+ }
+
+ if (isMoveStep && bRemoveFirst && ary.Data.length > 0)
+ {
+ var removeItem = ary.Data.shift();
+ this.OnItemPlayEnd(obj.HQChart, removeItem);
+ }
+
+ yOffset += lineHeight;
+ }
+
+ return list;
+ }
+
+ //根据高度计算播放队列个数
+ this.CacluatePlayLine = function (height)
+ {
+ this.Height = height;
+ var lineCount = parseInt(height / this.MinLineHeight);
+ if (this.PlayList.length < lineCount)
+ {
+ var addCount = lineCount - this.PlayList.length;
+ for (var i = 0; i < addCount; ++i)
+ {
+ this.PlayList.push({ Data: [] });
+ }
+ }
+ else if (this.PlayList.length > lineCount)
+ {
+ var removeCount = this.PlayList.length - lineCount;
+ for (var i = 0; i < removeCount; ++i)
+ {
+ var ary = this.PlayList.pop();
+ for (var j = 0; j < ary.Data.length; ++j)
+ {
+ var item = ary.Data[j];
+ var cacheItem = { Text: item.Text, Color: item.Color, Font: item.Font, Info: item.Info };
+ this.Cache.unshift(cacheItem);
+ }
+ }
+ }
+
+ JSConsole.Chart.Log(`[BarrageList::CacluatePlayLine] LineCount=${this.PlayList.length} Height=${this.Height}`)
+ }
+
+ //添加弹幕
+ this.AddBarrage = function (barrageData)
+ {
+ for (var i in barrageData) {
+ var item = barrageData[i];
+ this.Cache.push(item);
+ }
+ }
+
+ this.OnItemPlayEnd = function (hqChart, item) //单挑弹幕播放完毕
+ {
+ //监听事件
+ var event = hqChart.GetBarrageEvent();
+ if (!event || !event.Callback) return;
+
+ event.Callback(event, item, this);
+ }
+
+ this.Count = function () { return this.Cache.length; } //未播放的弹幕个数
+}
+
+//背景图 支持横屏
+function BackgroundPaint()
+{
+ this.newMethod = IExtendChartPainting; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.ClassName = 'BackgroundPaint';
+
+ this.IsDynamic = false;
+ this.IsCallbackDraw = true; //在回调函数里绘制, 不在Draw()中绘制
+
+ this.FrameID = 0;
+ this.Data; //背景数据 { Start:, End:, Color:[] }
+ this.ID = Guid(); //唯一的ID
+
+ /*
+ this.Data=
+ [
+ { Start:{ Date:20181201 }, End:{ Date:20181230 }, Color:'rgb(44,55,44)' } ,
+ { Start:{ Date:20190308 }, End:{ Date:20190404 }, Color:['rgb(44,55,255)','rgb(200,55,255)'] }
+ ]
+ */
+
+ this.ChartSubFrame;
+ this.ChartBorder;
+ this.KData;
+ this.Period;
+ this.XPointCount = 0;
+
+ this.SetOption = function (option) //设置
+ {
+ if (option.FrameID > 0) this.FrameID = option.FrameID;
+ if (IFrameSplitOperator.IsObjectExist(option.ID)) this.ID = option.ID;
+ }
+
+ this.Draw = function ()
+ {
+ if (!this.Data || !this.HQChart) return;
+ if (!this.ChartFrame || !this.ChartFrame.SubFrame || this.ChartFrame.SubFrame.length <= this.FrameID) return;
+ var klineChart = this.HQChart.ChartPaint[0];
+ if (!klineChart || !klineChart.Data) return;
+
+ this.ChartSubFrame = this.ChartFrame.SubFrame[this.FrameID].Frame;
+ this.ChartBorder = this.ChartSubFrame.ChartBorder;
+ this.KData = klineChart.Data;
+ this.Period = this.HQChart.Period;
+ if (!this.KData || this.KData.Data.length <= 0) return;
+
+ var isHScreen = (this.ChartSubFrame.IsHScreen === true);
+ this.XPointCount = this.ChartSubFrame.XPointCount;
+ var xPointCount = this.ChartSubFrame.XPointCount;
+
+ var firstKItem = this.KData.Data[this.KData.DataOffset];
+ var endIndex = this.KData.DataOffset + xPointCount - 1;
+ if (endIndex >= this.KData.Data.length) endIndex = this.KData.Data.length - 1;
+ var endKItem = this.KData.Data[endIndex];
+ var showData = this.GetShowData(firstKItem, endKItem);
+ if (!showData || showData.length <= 0) return;
+
+ var kLineMap = this.BuildKLineMap();
+ var bottom = this.ChartBorder.GetBottomEx();
+ var top = this.ChartBorder.GetTopEx();
+ var height = this.ChartBorder.GetHeightEx();
+ if (isHScreen)
+ {
+ top = this.ChartBorder.GetRightEx();
+ bottom = this.ChartBorder.GetLeftEx();
+ height = this.ChartBorder.GetWidthEx();
+ }
+
+ for (var i in showData)
+ {
+ var item = showData[i];
+ var rt = this.GetBGCoordinate(item, kLineMap);
+ if (!rt) continue;
+
+ if (Array.isArray(item.Color))
+ {
+ var gradient;
+ if (isHScreen) gradient = this.Canvas.createLinearGradient(bottom, rt.Left, top, rt.Left);
+ else gradient = this.Canvas.createLinearGradient(rt.Left, top, rt.Left, bottom);
+ var offset = 1 / item.Color.length;
+ for (var i in item.Color)
+ {
+ gradient.addColorStop(i * offset, item.Color[i]);
+ }
+ this.Canvas.fillStyle = gradient;
+ }
+ else
+ {
+ this.Canvas.fillStyle = item.Color;
+ }
+
+ if (isHScreen) this.Canvas.fillRect(ToFixedRect(bottom), ToFixedRect(rt.Left), ToFixedRect(height), ToFixedRect(rt.Width));
+ else this.Canvas.fillRect(ToFixedRect(rt.Left), ToFixedRect(top), ToFixedRect(rt.Width), ToFixedRect(height));
+ }
+ }
+
+ this.GetShowData = function (first, end)
+ {
+ var aryData = [];
+ for (var i in this.Data) {
+ var item = this.Data[i];
+ var showItem = {};
+ if (item.Start.Date >= first.Date && item.Start.Date <= end.Date) showItem.Start = item.Start;
+ if (item.End.Date >= first.Date && item.End.Date <= end.Date) showItem.End = item.End;
+ if (showItem.Start || showItem.End)
+ {
+ showItem.Color = item.Color;
+ aryData.push(showItem);
+ }
+ }
+
+ return aryData;
+ }
+
+ this.BuildKLineMap = function ()
+ {
+ var isHScreen = (this.ChartSubFrame.IsHScreen === true);
+ var dataWidth = this.ChartSubFrame.DataWidth;
+ var distanceWidth = this.ChartSubFrame.DistanceWidth;
+ var xOffset = this.ChartBorder.GetLeft() + distanceWidth / 2.0 + g_JSChartResource.FrameLeftMargin;
+ if (isHScreen) xOffset = this.ChartBorder.GetTop() + distanceWidth / 2.0 + g_JSChartResource.FrameLeftMargin;
+ var chartright = this.ChartBorder.GetRight();
+ if (isHScreen) chartright = this.ChartBorder.GetBottom();
+
+ var mapKLine = { Data: new Map() }; //Key: date / date time, Value:索引
+ for (var i = this.KData.DataOffset, j = 0; i < this.KData.Data.length && j < this.XPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth))
+ {
+ var kItem = this.KData.Data[i];
+ var left = xOffset;
+ var right = xOffset + dataWidth;
+ if (right > chartright) break;
+ var x = left + (right - left) / 2;
+
+ if (j == 0) mapKLine.XLeft = left;
+ mapKLine.XRight = right;
+
+ var value = { Index: i, ShowIndex: j, X: x, Right: right, Left: left, Date: kItem.Date };
+ if (ChartData.IsMinutePeriod(this.Period, true))
+ {
+ var key = `Date:${kItem.Date} Time:${kItem.Time}`;
+ value.Time = kItem.Time;
+ }
+ else
+ {
+ var key = `Date:${kItem.Date}`;
+ }
+
+ mapKLine.Data.set(key, value);
+ }
+
+ return mapKLine;
+ }
+
+ this.GetBGCoordinate = function (item, kLineMap)
+ {
+ var xLeft = null, xRight = null;
+ if (item.Start)
+ {
+ if (ChartData.IsMinutePeriod(this.Period, true))
+ var key = `Date:${item.Start.Date} Time:${item.Start.Time}`;
+ else
+ var key = `Date:${item.Start.Date}`;
+
+ if (kLineMap.Data.has(key))
+ {
+ var findItem = kLineMap.Data.get(key);
+ xLeft = findItem.Left;
+ }
+ else
+ {
+ for (var kItem of kLineMap.Data)
+ {
+ var value = kItem[1];
+ if (value.Date > item.Start.Date)
+ {
+ xLeft = value.Left;
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ xLeft = kLineMap.XLeft;
+ }
+
+ if (item.End)
+ {
+ if (ChartData.IsMinutePeriod(this.Period, true))
+ var key = `Date:${item.End.Date} Time:${item.End.Time}`;
+ else
+ var key = `Date:${item.End.Date}`;
+
+ if (kLineMap.Data.has(key))
+ {
+ var findItem = kLineMap.Data.get(key);
+ xRight = findItem.Right;
+ }
+ else
+ {
+ var previousX = null;
+ for (var kItem of kLineMap.Data)
+ {
+ var value = kItem[1];
+ if (value.Date > item.End.Date)
+ {
+ xRight = previousX;
+ break;
+ }
+ previousX = value.Right;
+ }
+ }
+ }
+ else
+ {
+ xRight = kLineMap.XRight;
+ }
+
+ if (xLeft == null || xRight == null) return null;
+
+ return { Left: xLeft, Right: xRight, Width: xRight - xLeft };
+ }
+}
+
+
+//弹幕
+function BarragePaint()
+{
+ this.newMethod = IExtendChartPainting; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.ClassName = 'BarragePaint';
+ this.IsAnimation = true;
+ this.IsEraseBG = true;
+ this.HQChart;
+
+ this.Font = g_JSChartResource.Barrage.Font;
+ this.TextColor = g_JSChartResource.Barrage.Color;
+ this.FontHeight = g_JSChartResource.Barrage.Height;
+
+ this.BarrageList = new BarrageList(); //字幕列表
+ this.IsMoveStep = false;
+
+
+ this.SetOption = function (option) //设置参数接口
+ {
+ if (option)
+ {
+ if (option.Step > 0) this.BarrageList.Step = option.Step;
+ if (option.MinLineHeight) this.Barrage.MinLineHeight = option.MinLineHeight;
+ }
+ }
+
+ this.DrawHScreen = function ()
+ {
+ var height = this.ChartBorder.GetWidth();
+ var left = this.ChartBorder.GetTop();
+ var right = this.ChartBorder.GetBottom();
+ var top = this.ChartBorder.GetRightEx();
+ var wdith = this.ChartBorder.GetChartWidth();
+
+ if (height != this.BarrageList.Height)
+ this.BarrageList.CacluatePlayLine(height);
+
+ this.Canvas.textBaseline = "middle";
+ this.Canvas.textAlign = "left";
+
+ var play = this.BarrageList.GetPlayList({ Canves: this.Canvas, Right: right, Left: left, Font: this.Font, IsMoveStep: this.IsMoveStep, HQChart: this.HQChart });
+ this.IsMoveStep = false;
+ if (!play) return;
+
+ this.Canvas.save();
+ this.Canvas.translate(this.ChartBorder.GetChartHeight(), 0);
+ this.Canvas.rotate(90 * Math.PI / 180);
+
+ for (var i = 0; i < play.length; ++i)
+ {
+ var item = play[i];
+ if (item.Color) this.Canvas.fillStyle = item.Color;
+ else this.Canvas.fillStyle = this.TextColor;
+ if (item.Font) this.Canvas.font = item.Font.Name;
+ else this.Canvas.font = this.Font;
+
+ var fontHeight = this.FontHeight;
+ if (item.Font && item.Font.Height > 0) fontHeight = item.Font.Height;
+ var yOffset = item.Y + parseInt((item.Height - fontHeight) / 2);
+
+ this.Canvas.fillText(item.Text, right - item.X, top + yOffset);
+ }
+
+ this.Canvas.restore();
+ }
+
+ this.Draw = function ()
+ {
+ if (this.ChartFrame.IsHScreen)
+ {
+ this.DrawHScreen();
+ return;
+ }
+
+ var left = this.ChartBorder.GetLeft();
+ var right = this.ChartBorder.GetRight();
+ var top = this.ChartBorder.GetTopEx();
+ var height = this.ChartBorder.GetHeight();
+
+ if (height != this.BarrageList.Height)
+ this.BarrageList.CacluatePlayLine(height);
+
+ this.Canvas.textBaseline = "middle";
+ this.Canvas.textAlign = "left";
+
+ var play = this.BarrageList.GetPlayList({ Canves: this.Canvas, Right: right, Left: left, Font: this.Font, IsMoveStep: this.IsMoveStep, HQChart: this.HQChart });
+ this.IsMoveStep = false;
+ if (!play) return;
+
+ for (var i = 0; i < play.length; ++i)
+ {
+ var item = play[i];
+ if (item.Color) this.Canvas.fillStyle = item.Color;
+ else this.Canvas.fillStyle = this.TextColor;
+ if (item.Font) this.Canvas.font = item.Font.Name;
+ else this.Canvas.font = this.Font;
+
+ var fontHeight = this.FontHeight;
+ if (item.Font && item.Font.Height > 0) fontHeight = item.Font.Height;
+ var yOffset = item.Y + parseInt((item.Height - fontHeight) / 2);
+
+ this.Canvas.fillText(item.Text, right - item.X, top + yOffset);
+ }
+ }
+}
+
+//导出统一使用JSCommon命名空间名
+module.exports =
+{
+ JSCommonExtendChartPaint:
+ {
+ IExtendChartPainting: IExtendChartPainting,
+ KLineTooltipPaint: KLineTooltipPaint,
+ BarragePaint: BarragePaint,
+ MinuteTooltipPaint: MinuteTooltipPaint,
+ BackgroundPaint: BackgroundPaint,
+ },
+
+ //单个类导出
+ JSCommonExtendChartPaint_IExtendChartPainting: IExtendChartPainting,
+ JSCommonExtendChartPaint_KLineTooltipPaint: KLineTooltipPaint,
+ JSCommonExtendChartPaint_BarragePaint: BarragePaint,
+ JSCommonExtendChartPaint_MinuteTooltipPaint: MinuteTooltipPaint,
+ JSCommonExtendChartPaint_BackgroundPaint: BackgroundPaint,
+};
\ No newline at end of file
diff --git a/uni_modules/jones-hqchart2/js_sdk/umychart.framesplit.wechat.js b/uni_modules/jones-hqchart2/js_sdk/umychart.framesplit.wechat.js
new file mode 100644
index 0000000..ed4be6b
--- /dev/null
+++ b/uni_modules/jones-hqchart2/js_sdk/umychart.framesplit.wechat.js
@@ -0,0 +1,2024 @@
+/*
+ copyright (c) 2018 jones
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ 开源项目 https://github.com/jones2000/HQChart
+
+ jones_2000@163.com
+
+ 坐标轴相关算法
+*/
+
+import
+{
+ JSCommonResource_Global_JSChartResource as g_JSChartResource,
+ JSCommonResource_JSCHART_LANGUAGE_ID as JSCHART_LANGUAGE_ID,
+ JSCommonResource_Global_JSChartLocalization as g_JSChartLocalization,
+} from './umychart.resource.wechat.js'
+
+import {
+ JSCommon_ChartData as ChartData, JSCommon_HistoryData as HistoryData,
+ JSCommon_SingleData as SingleData, JSCommon_MinuteData as MinuteData,
+ JSCommon_JSCHART_EVENT_ID as JSCHART_EVENT_ID,
+} from "./umychart.data.wechat.js";
+
+import { JSCommonCoordinateData as JSCommonCoordinateData } from "./umychart.coordinatedata.wechat.js";
+var MARKET_SUFFIX_NAME = JSCommonCoordinateData.MARKET_SUFFIX_NAME;
+
+var WEEK_NAME=["日","一","二","三","四","五","六"];
+
+//坐标信息
+function CoordinateInfo()
+{
+ this.Value; //坐标数据
+ this.Message = new Array(); //坐标输出文字信息
+ this.TextColor = g_JSChartResource.FrameSplitTextColor //文字颜色
+ this.Font = g_JSChartResource.FrameSplitTextFont; //字体
+ this.LineColor = g_JSChartResource.FrameSplitPen; //线段颜色
+ this.LineType = 1; //线段类型 -1 不画线段
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+//坐标分割
+//
+//
+////////////////////////////////////////////////////////////////////////////////////////////////////
+function IFrameSplitOperator()
+{
+ this.ChartBorder; //边框信息
+ this.Frame; //框架信息
+ this.FrameSplitData; //坐标轴分割方法
+ this.SplitCount = 5; //刻度个数
+ this.StringFormat = 0; //刻度字符串格式 -1 刻度文字全部不显示 -2 刻度文字右边不显示
+ this.IsShowLeftText = true; //显示左边刻度
+ this.IsShowRightText = true; //显示右边刻度
+ this.LanguageID = JSCHART_LANGUAGE_ID.LANGUAGE_CHINESE_ID;
+ this.GetEventCallback; //事件回调
+
+ //////////////////////
+ // data.Min data.Max data.Interval data.Count
+ //
+ this.IntegerCoordinateSplit = function (data)
+ {
+ var splitItem = this.FrameSplitData.Find(data.Interval);
+ if (!splitItem) return false;
+ if (data.Interval == splitItem.Interval) return true;
+
+ var fixMax=data.Max, fixMin=data.Min;
+ var maxValue=data.Max/splitItem.FixInterval;
+ var minValue=data.Min/splitItem.FixInterval;
+ //调整到整数倍数,不能整除的 +1
+ if (IFrameSplitOperator.IsFloat(maxValue)) fixMax=parseInt((maxValue+0.5).toFixed(0))*splitItem.FixInterval;
+ if (IFrameSplitOperator.IsFloat(minValue)) fixMin=parseInt((minValue-0.5).toFixed(0))*splitItem.FixInterval;
+ if (data.Min == 0) fixMin = 0; //最小值是0 不用调整了.
+ if (fixMin < 0 && data.Min > 0) fixMin = 0; //都是正数的, 最小值最小调整为0
+
+ var count = 0;
+ for (var i = fixMin; (i - fixMax) < 0.00000001; i += splitItem.FixInterval)
+ {
+ ++count;
+ }
+
+ data.Interval = splitItem.FixInterval;
+ data.Max = fixMax;
+ data.Min = fixMin;
+ data.Count = count;
+
+ return true;
+ }
+
+ this.Filter = function (aryInfo, keepZero) //keepZero 保留0轴
+ {
+ if (this.SplitCount <= 0 || aryInfo.length <= 0 || aryInfo.length <= this.SplitCount) return aryInfo;
+
+ //分割线比预设的多, 过掉一些
+ var filter = parseInt(aryInfo.length / this.SplitCount);
+ if (filter <= 1) filter = 2;
+ var data = [];
+
+ for (var i = 0; i < aryInfo.length; i += filter)
+ {
+ if (i + filter >= aryInfo.length && i != aryInfo.length - 1) //最后一个数据放进去
+ {
+ data.push(aryInfo[aryInfo.length - 1]);
+ }
+ else {
+ data.push(aryInfo[i]);
+ }
+ }
+
+ if (this.SplitCount == 2 && data.length > 2) //之显示第1个和最后一个刻度
+ {
+ for (var i = 1; i < data.length - 1; ++i)
+ {
+ var item = data[i];
+ item.Message[0] = null;
+ item.Message[1] = null;
+ }
+ }
+
+ if (keepZero) //如果不存在0轴,增加一个0轴,刻度信息部显示
+ {
+ var bExsitZero = false;
+ for (var i = 0; i < data; ++i)
+ {
+ var item = data[i];
+ if (Math.abs(item.Value) < 0.00000001)
+ {
+ bExsitZero = true;
+ break;
+ }
+ }
+
+ if (bExsitZero == false)
+ {
+ var zeroCoordinate = new CoordinateInfo();
+ zeroCoordinate.Value = 0;
+ zeroCoordinate.Message[0] = null
+ zeroCoordinate.Message[1] = null;
+ data.push(zeroCoordinate);
+ }
+ }
+
+ return data;
+ }
+
+ this.RemoveZero = function (aryInfo) //移除小数后面多余的0
+ {
+ //所有的数字小数点后面都0,才会去掉
+ var isAllZero = [true, true];
+ for (var i in aryInfo) {
+ var item = aryInfo[i];
+ var message = item.Message[0];
+ if (!this.IsDecimalZeroEnd(message)) isAllZero[0] = false;
+
+ var message = item.Message[1];
+ if (!this.IsDecimalZeroEnd(message)) isAllZero[1] = false;
+ }
+
+ if (isAllZero[0] == false && isAllZero[1] == false) return;
+ for (var i in aryInfo)
+ {
+ var item = aryInfo[i];
+ if (isAllZero[0])
+ {
+ var message = item.Message[0];
+ if (message != null)
+ {
+ if (typeof (message) == 'number') message = message.toString();
+ item.Message[0] = message.replace(/[.][0]+/g, '');
+ }
+ }
+
+ if (isAllZero[1])
+ {
+ var message = item.Message[1];
+ if (message != null)
+ {
+ if (typeof (message) == 'number') message = message.toString();
+ item.Message[1] = message.replace(/[.][0]+/g, '');
+ }
+ }
+ }
+ }
+
+ this.IsDecimalZeroEnd = function (text) //是否是0结尾的小数
+ {
+ if (text == null) return true;
+ if (text == '0') return true;
+ if (typeof (text) == 'number') text = text.toString();
+
+ var pos = text.search(/[.]/);
+ if (pos < 0) return false;
+
+ for (var i = pos + 1; i < text.length; ++i)
+ {
+ var char = text.charAt(i);
+ if (char >= '1' && char <= '9') return false;
+ }
+
+ return true;
+ }
+}
+
+//字符串格式化 千分位分割
+IFrameSplitOperator.FormatValueThousandsString=function(value,floatPrecision)
+{
+ if (value==null || isNaN(value))
+ {
+ if (floatPrecision>0)
+ {
+ var nullText='-.';
+ for(var i=0;i0){
+ var numFloat = num.split('.')[1];
+ var numM = num.split('.')[0];
+ while (numM.length > 3)
+ {
+ result = ',' + numM.slice(-3) + result;
+ numM = numM.slice(0, numM.length - 3);
+ }
+ if (numM) { result = numM + result + '.' + numFloat; }
+ }else{
+ while (num.length > 3)
+ {
+ result = ',' + num.slice(-3) + result;
+ num = num.slice(0, num.length - 3);
+ }
+ if (num) { result = num + result; }
+ }
+
+ return result;
+}
+
+//数据输出格式化 floatPrecision=小数位数
+IFrameSplitOperator.FormatValueString=function(value, floatPrecision,languageID)
+{
+ if (value==null || isNaN(value))
+ {
+ if (floatPrecision>0)
+ {
+ var nullText='-.';
+ for(var i=0;i-0.00000000001)
+ {
+ return "0";
+ }
+
+ var absValue = Math.abs(value);
+ if (languageID===JSCHART_LANGUAGE_ID.LANGUAGE_ENGLISH_ID)
+ {
+ if (absValue < 10000)
+ return value.toFixed(floatPrecision);
+ else if (absValue < 1000000)
+ return (value/1000).toFixed(floatPrecision)+"K";
+ else if (absValue < 1000000000)
+ return (value/1000000).toFixed(floatPrecision)+"M";
+ else if (absValue < 1000000000000)
+ return (value/1000000000).toFixed(floatPrecision)+"B";
+ else
+ return (value/1000000000000).toFixed(floatPrecision)+"T";
+ }
+ else
+ {
+ if (absValue < 10000)
+ return value.toFixed(floatPrecision);
+ else if (absValue < 100000000)
+ return (value/10000).toFixed(floatPrecision)+"万";
+ else if (absValue < 1000000000000)
+ return (value/100000000).toFixed(floatPrecision)+"亿";
+ else
+ return (value/1000000000000).toFixed(floatPrecision)+"万亿";
+ }
+
+ return '';
+}
+
+//整形输出格式化 floatPrecision=小数位数
+IFrameSplitOperator.FromatIntegerString=function(value, floatPrecision,languageID)
+{
+ if (value<10000 && IFrameSplitOperator.IsInteger(value)) floatPrecision=0; //<10000的整形 去掉小数位数
+ return IFrameSplitOperator.FormatValueString(value, floatPrecision,languageID);
+}
+
+IFrameSplitOperator.NumberToString=function(value)
+{
+ if (value<10) return '0'+value.toString();
+ return value.toString();
+}
+
+IFrameSplitOperator.FormatDateString=function(value,format,languageID)
+{
+ var year=parseInt(value/10000);
+ var month=parseInt(value/100)%100;
+ var day=value%100;
+
+ switch(format)
+ {
+ case 'MM-DD':
+ return IFrameSplitOperator.NumberToString(month) + '-' + IFrameSplitOperator.NumberToString(day);
+ case "YYYY/MM/DD":
+ return year.toString() + '/' + IFrameSplitOperator.NumberToString(month) + '/' + IFrameSplitOperator.NumberToString(day);
+ case "YYYY/MM/DD/W":
+ {
+ var date=new Date(year,month-1,day);
+ var week=g_JSChartLocalization.GetText(WEEK_NAME[date.getDay()],languageID);
+ return year.toString() + '/' + IFrameSplitOperator.NumberToString(month) + '/' + IFrameSplitOperator.NumberToString(day)+"/"+ week.toString();
+ }
+ case "DD/MM/YYYY":
+ return IFrameSplitOperator.NumberToString(day) + '/' + IFrameSplitOperator.NumberToString(month) + '/' + year.toString();
+ default:
+ return year.toString() + '-' + IFrameSplitOperator.NumberToString(month) + '-' + IFrameSplitOperator.NumberToString(day);
+ }
+}
+
+IFrameSplitOperator.FormatTimeString=function(value, format) //format hh:mm:ss
+{
+ if (format=='HH:MM:SS')
+ {
+ var hour=parseInt(value/10000);
+ var minute=parseInt((value%10000)/100);
+ var second=value%100;
+ return IFrameSplitOperator.NumberToString(hour)+':'+ IFrameSplitOperator.NumberToString(minute) + ':' + IFrameSplitOperator.NumberToString(second);
+ }
+ else if (format == 'HH:MM')
+ {
+ var hour = parseInt(value / 100);
+ var minute = value % 100;
+ return IFrameSplitOperator.NumberToString(hour) + ':' + IFrameSplitOperator.NumberToString(minute);
+ }
+ else
+ {
+ if (value < 10000)
+ {
+ var hour = parseInt(value / 100);
+ var minute = value % 100;
+ return IFrameSplitOperator.NumberToString(hour) + ':' + IFrameSplitOperator.NumberToString(minute);
+ }
+ else
+ {
+ var hour = parseInt(value / 10000);
+ var minute = parseInt((value % 10000) / 100);
+ var second = value % 100;
+ return IFrameSplitOperator.NumberToString(hour) + ':' + IFrameSplitOperator.NumberToString(minute) + ':' + IFrameSplitOperator.NumberToString(second);
+ }
+
+ }
+}
+
+//报告格式化
+IFrameSplitOperator.FormatReportDateString=function(value)
+{
+ var year=parseInt(value/10000);
+ var month=parseInt(value/100)%100;
+ var monthText;
+ switch(month)
+ {
+ case 3:
+ monthText="一季度报";
+ break;
+ case 6:
+ monthText="半年报";
+ break;
+ case 9:
+ monthText="三季度报";
+ break;
+ case 12:
+ monthText="年报";
+ break;
+ }
+
+ return year.toString()+ monthText;
+}
+
+IFrameSplitOperator.FormatDateTimeString=function(value,isShowDate)
+{
+ var aryValue=value.split(' ');
+ if (aryValue.length<2) return "";
+ var time=parseInt(aryValue[1]);
+ var minute=time%100;
+ var hour=parseInt(time/100);
+ var text=(hour<10? ('0'+hour.toString()):hour.toString()) + ':' + (minute<10?('0'+minute.toString()):minute.toString());
+
+ if (isShowDate==true)
+ {
+ var date=parseInt(aryValue[0]);
+ var year=parseInt(date/10000);
+ var month=parseInt(date%10000/100);
+ var day=date%100;
+ text=year.toString() +'-'+ (month<10? ('0'+month.toString()) :month.toString()) +'-'+ (day<10? ('0'+day.toString()):day.toString()) +" " +text;
+ }
+
+ return text;
+}
+
+//字段颜色格式化
+IFrameSplitOperator.FormatValueColor = function (value, value2)
+{
+ if (value != null && value2 == null) //只传一个值的 就判断value正负
+ {
+ if (value == 0) return 'PriceNull';
+ else if (value > 0) return 'PriceUp';
+ else return 'PriceDown';
+ }
+
+ //2个数值对比 返回颜色
+ if (value == null || value2 == null) return 'PriceNull';
+ if (value == value2) return 'PriceNull';
+ else if (value > value2) return 'PriceUp';
+ else return 'PriceDown';
+}
+
+IFrameSplitOperator.IsNumber=function(value)
+{
+ if (value==null) return false;
+ if (isNaN(value)) return false;
+
+ return true;
+}
+
+//判断是否是正数
+IFrameSplitOperator.IsPlusNumber=function(value)
+{
+ if (value==null) return false;
+ if (isNaN(value)) return false;
+
+ return value>0;
+}
+
+//是否是整形
+IFrameSplitOperator.IsInteger=function(x)
+{
+ return (typeof x === 'number') && (x % 1 === 0);
+}
+
+//判断字段是否存在
+IFrameSplitOperator.IsObjectExist=function(obj)
+{
+ if (obj===undefined) return false;
+ if (obj==null) return false;
+
+ return true;
+}
+
+//是否时bool
+IFrameSplitOperator.IsBool=function(value)
+{
+ if (value===true || value===false) return true;
+ return false;
+}
+
+IFrameSplitOperator.IsString=function(value)
+{
+ var type=typeof(value);
+ if (type=='string') return true;
+ return false;
+}
+
+IFrameSplitOperator.IsFloat=function(value)
+{
+ if (value===undefined) return false;
+ if (value==null) return false;
+ if (isNaN(value)) return false;
+
+ return value!=parseInt(value);
+}
+
+//是否是非空的数组
+IFrameSplitOperator.IsNonEmptyArray=function(ary)
+{
+ if (!ary) return;
+ if (!Array.isArray(ary)) return;
+
+ return ary.length>0;
+}
+
+//K线Y轴分割
+function FrameSplitKLinePriceY()
+{
+ this.newMethod = IFrameSplitOperator; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.CoordinateType = 0; //坐标类型 0=普通坐标 1=百分比坐标 (右边坐标刻度)
+ this.Symbol;
+ this.Data; //K线数据 (计算百分比坐标)
+ this.FrameSplitData2; //坐标轴分割方法(计算百分比刻度)
+ this.FloatPrecision = null; //小数位数 (设置了就使用这个位数,否则使用品种对应的小数位数)
+
+ this.Custom = []; //[{Type:0}]; 定制刻度 0=显示最后的价格刻度
+ this.SplitType = 0; //0=自动分割 1=固定分割
+
+ this.Operator = function ()
+ {
+ var splitData = {};
+ splitData.Max = this.Frame.HorizontalMax;
+ splitData.Min = this.Frame.HorizontalMin;
+ splitData.Count = this.SplitCount;
+ if (splitData.Max==splitData.Min) //如果一样上下扩大下
+ {
+ splitData.Max+=splitData.Max*0.01;
+ splitData.Min-=splitData.Min*0.01
+ }
+ splitData.Interval = (splitData.Max - splitData.Min) / (splitData.Count - 1);
+
+ var defaultfloatPrecision = JSCommonCoordinateData.GetfloatPrecision(this.Symbol);
+ if (JSCommonCoordinateData.MARKET_SUFFIX_NAME.IsSHSZIndex(this.Symbol)) defaultfloatPrecision = 0; //手机端指数不显示小数位数
+ if (this.FloatPrecision != null) defaultfloatPrecision = this.FloatPrecision;
+
+ var bFilter=true;
+ if (FrameSplitKLinePriceY.SplitCustom)
+ {
+ FrameSplitKLinePriceY.SplitCustom(this,splitData,defaultfloatPrecision); //自定义分割
+ bFilter=false;
+ }
+ else
+ {
+ switch (this.CoordinateType)
+ {
+ case 1:
+ this.SplitPercentage(splitData, defaultfloatPrecision);
+ break;
+ default:
+ if (this.SplitType == 1) this.SplitFixed(splitData, defaultfloatPrecision);
+ else this.SplitDefault(splitData, defaultfloatPrecision);
+ this.CustomCoordinate(defaultfloatPrecision);
+ break;
+ }
+ }
+
+ if (bFilter) this.Frame.HorizontalInfo = this.Filter(this.Frame.HorizontalInfo, false);
+ this.Frame.HorizontalMax = splitData.Max;
+ this.Frame.HorizontalMin = splitData.Min;
+
+ if (this.GetEventCallback)
+ {
+ var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_SPLIT_YCOORDINATE);
+ if (event && event.Callback)
+ {
+ var data={ID:this.Frame.Identify, Frame:this.Frame };
+ event.Callback(event,data,this);
+ }
+ }
+ }
+
+ this.SplitDefault = function (splitData, floatPrecision) //默认坐标
+ {
+ this.IntegerCoordinateSplit(splitData);
+
+ this.Frame.HorizontalInfo = [];
+ for (var i = 0, value = splitData.Min; i < splitData.Count; ++i, value += splitData.Interval)
+ {
+ this.Frame.HorizontalInfo[i] = new CoordinateInfo();
+ this.Frame.HorizontalInfo[i].Value = value;
+ if (this.IsShowLeftText) this.Frame.HorizontalInfo[i].Message[0] = value.toFixed(floatPrecision);
+ if (this.IsShowRightText) this.Frame.HorizontalInfo[i].Message[1] = value.toFixed(floatPrecision);
+ }
+ }
+
+ this.SplitPercentage = function (splitData, floatPrecision) //百分比坐标
+ {
+ var firstOpenPrice = this.GetFirstOpenPrice();
+ splitData.Max = (splitData.Max - firstOpenPrice) / firstOpenPrice;
+ splitData.Min = (splitData.Min - firstOpenPrice) / firstOpenPrice;
+ splitData.Interval = (splitData.Max - splitData.Min) / (splitData.Count - 1);
+ this.IntegerCoordinateSplit2(splitData);
+
+ var maxValue=(1 + splitData.Max) * firstOpenPrice;
+ var minValue=(1 + splitData.Min) * firstOpenPrice;
+
+ this.Frame.HorizontalInfo = [];
+ for (var i = 0, value = splitData.Min; i < splitData.Count; ++i, value += splitData.Interval)
+ {
+ var price = (value + 1) * firstOpenPrice;
+ if (pricemaxValue) continue;
+
+ this.Frame.HorizontalInfo[i] = new CoordinateInfo();
+ this.Frame.HorizontalInfo[i].Value = price;
+ if (this.IsShowLeftText) this.Frame.HorizontalInfo[i].Message[0] = price.toFixed(floatPrecision); //左边价格坐标
+ if (this.IsShowRightText) this.Frame.HorizontalInfo[i].Message[1] = (value * 100).toFixed(2) + '%'; //右边百分比
+ }
+
+ splitData.Min = (1 + splitData.Min) * firstOpenPrice; //最大最小值调整
+ splitData.Max = (1 + splitData.Max) * firstOpenPrice;
+ }
+
+ this.SplitFixed = function (splitData, floatPrecision) //固定分割坐标
+ {
+ this.Frame.HorizontalInfo = [];
+ for (var i = 0, value = splitData.Min; i < splitData.Count; ++i, value += splitData.Interval) {
+ this.Frame.HorizontalInfo[i] = new CoordinateInfo();
+ this.Frame.HorizontalInfo[i].Value = value;
+ if (this.IsShowLeftText) this.Frame.HorizontalInfo[i].Message[0] = value.toFixed(floatPrecision);
+ if (this.IsShowRightText) this.Frame.HorizontalInfo[i].Message[1] = value.toFixed(floatPrecision);
+ }
+ }
+
+ this.CustomCoordinate = function (floatPrecision)
+ {
+ this.Frame.CustomHorizontalInfo = [];
+ for (var i in this.Custom)
+ {
+ var item = this.Custom[i];
+ if (item.Type == 0) //最新价格刻度
+ {
+ var dec=floatPrecision;
+ //外部设置小数位数
+ if (IFrameSplitOperator.IsNumber(item.FloatPrecision) && item.FloatPrecision>=0) dec=item.FloatPrecision;
+ var latestItem = this.GetLatestPrice(dec, item);
+ if (latestItem) this.Frame.CustomHorizontalInfo.push(latestItem);
+ }
+ else if (item.Type == 1) //固定价格刻度
+ {
+ this.CustomFixedCoordinate(item);
+ }
+ }
+ }
+
+ this.GetLatestPrice = function (floatPrecision, option)
+ {
+ if (!this.Data || !this.Data.Data) return null;
+ if (this.Data.Data.length <= 0) return null;
+ var latestItem = this.Data.Data[this.Data.Data.length - 1];
+ var info = new CoordinateInfo();
+ info.Type = 0;
+ info.Value = latestItem.Close;
+ info.TextColor = g_JSChartResource.FrameLatestPrice.TextColor;
+ info.LineType = 2; //虚线
+ if (option.Position == 'left') info.Message[0] = latestItem.Close.toFixed(floatPrecision);
+ else info.Message[1] = latestItem.Close.toFixed(floatPrecision);
+ if (latestItem.Close > latestItem.Open) info.LineColor = g_JSChartResource.FrameLatestPrice.UpBarColor;
+ else if (latestItem.Close < latestItem.Open) info.LineColor = g_JSChartResource.FrameLatestPrice.DownBarColor;
+ else info.LineColor = g_JSChartResource.FrameLatestPrice.UnchagneBarColor;
+
+ if (IFrameSplitOperator.IsNumber(option.LineType)) info.LineType=option.LineType;
+ if (option.IsShowLine == false) info.LineType = -1;
+
+ return info;
+ }
+
+ this.GetFirstOpenPrice = function () //获取显示第1个数据的开盘价
+ {
+ if (!this.Data) return null;
+ var xPointCount = this.Frame.XPointCount;
+ for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j)
+ {
+ var data = this.Data.Data[i];
+ if (data.Open == null || data.High == null || data.Low == null || data.Close == null) continue;
+
+ return data.Open;
+ }
+ return null;
+ }
+
+ this.CustomFixedCoordinate = function (option) //固定坐标刻度
+ {
+ var defaultfloatPrecision = JSCommonCoordinateData.GetfloatPrecision(this.Symbol);
+ for (var i in option.Data)
+ {
+ var item = option.Data[i];
+ var info = new CoordinateInfo();
+ info.Type = 1;
+ info.TextColor = item.TextColor;
+ info.LineColor = item.Color;
+ info.LineType = 2; //虚线
+ if (IFrameSplitOperator.IsNumber(option.LineType)) info.LineType=option.LineType;
+ if (option.IsShowLine == false) info.LineType = -1;
+
+ info.Value = item.Value;
+ var text;
+ if (item.Text) text = item.Text;
+ else text = info.Value.toFixed(defaultfloatPrecision);
+ if (option.Position == 'left') info.Message[0] = text;
+ else info.Message[1] = text;
+
+ this.Frame.CustomHorizontalInfo.push(info);
+ }
+ }
+
+
+ //////////////////////
+ // data.Min data.Max data.Interval data.Count
+ //
+ this.IntegerCoordinateSplit2 = function (data)
+ {
+ var splitItem = this.FrameSplitData2.Find(data.Interval);
+ if (!splitItem) return false;
+ if (data.Interval == splitItem.FixInterval) return true;
+
+ var fixMax=data.Max, fixMin=data.Min;
+ var maxValue=data.Max/splitItem.FixInterval;
+ var minValue=data.Min/splitItem.FixInterval;
+ //调整到整数倍数,不能整除的 +1
+ if (IFrameSplitOperator.IsFloat(maxValue)) fixMax=parseInt((maxValue+0.5).toFixed(0))*splitItem.FixInterval;
+ if (IFrameSplitOperator.IsFloat(minValue)) fixMin=parseInt((minValue-0.5).toFixed(0))*splitItem.FixInterval;
+ if (data.Min == 0) fixMin = 0; //最小值是0 不用调整了.
+ if (fixMin < 0 && data.Min > 0) fixMin = 0; //都是正数的, 最小值最小调整为0
+
+ var count = 0;
+ for (var i = fixMin; (i - fixMax) < 0.00000001; i += splitItem.FixInterval)
+ {
+ ++count;
+ }
+
+ data.Interval = splitItem.FixInterval;
+ data.Max = fixMax;
+ data.Min = fixMin;
+ data.Count = count;
+
+ return true;
+ }
+
+}
+
+//一般的Y轴分割
+function FrameSplitY()
+{
+ this.newMethod = IFrameSplitOperator; //派生
+ this.newMethod();
+ delete this.newMethod;
+ this.SplitType=0; //0=自动分割 1=固定分割
+ this.FloatPrecision = 2; //坐标小数位数(默认2)
+ this.FLOATPRECISION_RANGE = [1, 0.1, 0.01, 0.001, 0.0001];
+ this.IgnoreYValue = null; //在这个数组里的数字不显示在刻度上
+ this.LineType=null; //线段样式
+
+ this.IsShowYZero = true;
+ this.IntegerSplitData = null;
+
+ this.Operator = function ()
+ {
+ var splitData = {};
+ splitData.Max = this.Frame.HorizontalMax;
+ splitData.Min = this.Frame.HorizontalMin;
+
+ if (splitData.Max==splitData.Min) //如果一样上下扩大下
+ {
+ if (splitData.Max==0)
+ {
+ splitData.Max=1;
+ splitData.Min=-1;
+ }
+ else
+ {
+ splitData.Max+=splitData.Max*0.01;
+ splitData.Min-=splitData.Min*0.01;
+ }
+ }
+
+ if (this.Frame.YSpecificMaxMin)
+ {
+ splitData.Count = this.Frame.YSpecificMaxMin.Count;
+ splitData.Interval = (splitData.Max - splitData.Min) / (splitData.Count - 1);
+ }
+ else if (this.SplitType==1)
+ {
+ splitData.Count=this.SplitCount;
+ splitData.Interval=(splitData.Max-splitData.Min)/(splitData.Count-1);
+ }
+ else
+ {
+ splitData.Count = this.SplitCount * 2; //放大两倍
+ if (this.FloatPrecision == 0) //页面配置了纵坐标小数位数FloatPrecision=0时执行
+ {
+ splitData.Interval = (splitData.Max - splitData.Min) / (splitData.Count - 1);
+ this.IntegerCoordinateSplit2(splitData);
+ }
+ else {
+ splitData.Interval = (splitData.Max - splitData.Min) / (splitData.Count - 1);
+ this.IntegerCoordinateSplit(splitData);
+ }
+ }
+
+ this.Frame.HorizontalInfo = [];
+ if (this.Frame.YSplitScale)
+ {
+ for (var i in this.Frame.YSplitScale)
+ {
+ var value = this.Frame.YSplitScale[i];
+ var coordinate = new CoordinateInfo();
+ coordinate.Value = value;
+ if (IFrameSplitOperator.IsNumber(this.LineType)) coordinate.LineType=this.LineType;
+
+ var absValue = Math.abs(value);
+ var floatPrecision = this.FloatPrecision; //数据比小数位数还小, 调整小数位数
+ if (absValue < 0.0000000001)
+ coordinate.Message[1] = 0;
+ else if (absValue < this.FLOATPRECISION_RANGE[this.FLOATPRECISION_RANGE.length - 1])
+ coordinate.Message[1] = value.toExponential(2).toString();
+ else
+ {
+ if (floatPrecision < this.FLOATPRECISION_RANGE.length && absValue < this.FLOATPRECISION_RANGE[floatPrecision])++floatPrecision;
+ if (floatPrecision < this.FLOATPRECISION_RANGE.length && absValue < this.FLOATPRECISION_RANGE[floatPrecision])++floatPrecision;
+ if (floatPrecision < this.FLOATPRECISION_RANGE.length && absValue < this.FLOATPRECISION_RANGE[floatPrecision])++floatPrecision;
+ coordinate.Message[1] = IFrameSplitOperator.FormatValueString(value, floatPrecision, this.LanguageID);
+ }
+ coordinate.Message[0] = coordinate.Message[1];
+
+ if (this.StringFormat == -2) coordinate.Message[1] = null; //刻度右边不显示
+ else if (this.StringFormat == -3) coordinate.Message[0] = null; //刻度左边不显示
+ else if (this.StringFormat == -1) coordinate.Message[0] = coordinate.Message[1] = null; //刻度左右都不显示
+
+ this.Frame.HorizontalInfo.push(coordinate);
+ }
+ }
+ else
+ {
+ for (var i = 0, value = splitData.Min; i < splitData.Count; ++i, value += splitData.Interval)
+ {
+ var coordinate=new CoordinateInfo();
+ this.Frame.HorizontalInfo[i] = coordinate;
+ coordinate.Value=value;
+ if (IFrameSplitOperator.IsNumber(this.LineType)) coordinate.LineType=this.LineType;
+
+ if (this.StringFormat == 1) //手机端格式 如果有万,亿单位了 去掉小数
+ {
+ var floatPrecision = this.FloatPrecision;
+ if (!isNaN(value) && Math.abs(value) > 1000) floatPrecision = 0;
+ this.Frame.HorizontalInfo[i].Message[1] = IFrameSplitOperator.FormatValueString(value, floatPrecision, this.LanguageID);
+ }
+ else if (this.StringFormat == -1) //刻度不显示
+ {
+
+ }
+ else
+ {
+ var absValue = Math.abs(value);
+ var floatPrecision = this.FloatPrecision; //数据比小数位数还小, 调整小数位数
+ if (absValue < 0.0000000001)
+ this.Frame.HorizontalInfo[i].Message[1] = 0;
+ else if (absValue < this.FLOATPRECISION_RANGE[this.FLOATPRECISION_RANGE.length - 1])
+ this.Frame.HorizontalInfo[i].Message[1] = value.toExponential(2).toString();
+ else {
+ if (floatPrecision < this.FLOATPRECISION_RANGE.length && absValue < this.FLOATPRECISION_RANGE[floatPrecision])++floatPrecision;
+ if (floatPrecision < this.FLOATPRECISION_RANGE.length && absValue < this.FLOATPRECISION_RANGE[floatPrecision])++floatPrecision;
+ if (floatPrecision < this.FLOATPRECISION_RANGE.length && absValue < this.FLOATPRECISION_RANGE[floatPrecision])++floatPrecision;
+ this.Frame.HorizontalInfo[i].Message[1] = IFrameSplitOperator.FormatValueString(value, floatPrecision, this.LanguageID);
+ }
+ }
+
+ this.Frame.HorizontalInfo[i].Message[0] = this.Frame.HorizontalInfo[i].Message[1];
+
+ if (this.StringFormat == -2) this.Frame.HorizontalInfo[i].Message[1] = null; //刻度右边不显示
+ else if (this.StringFormat == -3) this.Frame.HorizontalInfo[i].Message[0] = null; //刻度左边不显示
+ }
+ }
+
+ this.FilterIgnoreYValue();
+ this.Frame.HorizontalInfo = this.Filter(this.Frame.HorizontalInfo, (splitData.Max > 0 && splitData.Min < 0 && this.IsShowYZero));
+ this.RemoveZero(this.Frame.HorizontalInfo);
+ this.Frame.HorizontalMax = splitData.Max;
+ this.Frame.HorizontalMin = splitData.Min;
+
+ if (this.GetEventCallback)
+ {
+ var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_SPLIT_YCOORDINATE);
+ if (event && event.Callback)
+ {
+ var data={ID:this.Frame.Identify, Frame:this.Frame };
+ event.Callback(event,data,this);
+ }
+ }
+ }
+
+ this.FilterIgnoreYValue = function ()
+ {
+ if (!this.IgnoreYValue || this.IgnoreYValue.length <= 0) return;
+
+ var setValue = new Set(this.IgnoreYValue);
+ this.Frame.HorizontalInfo = this.Frame.HorizontalInfo.filter(item => !setValue.has(item.Value));
+ this.IsShowYZero = !setValue.has(0); //是否显示0刻度
+ }
+
+ this.IntegerCoordinateSplit2 = function (data) //整数分割
+ {
+ if (this.IntegerSplitData == null) this.IntegerSplitData = new IntegerSplitData();
+ var splitItem = this.IntegerSplitData.Find(data.Interval);
+ if (!splitItem) return false;
+ if (data.Interval == splitItem.FixInterval) return true;
+
+ var fixMax=data.Max, fixMin=data.Min;
+ var maxValue=data.Max/splitItem.FixInterval;
+ var minValue=data.Min/splitItem.FixInterval;
+ //调整到整数倍数,不能整除的 +1
+ if (IFrameSplitOperator.IsFloat(maxValue)) fixMax=parseInt((maxValue+0.5).toFixed(0))*splitItem.FixInterval;
+ if (IFrameSplitOperator.IsFloat(minValue)) fixMin=parseInt((minValue-0.5).toFixed(0))*splitItem.FixInterval;
+ if (data.Min == 0) fixMin = 0; //最小值是0 不用调整了.
+ if (fixMin < 0 && data.Min > 0) fixMin = 0; //都是正数的, 最小值最小调整为0
+
+ var count = 0;
+ for (var i = fixMin; (i - fixMax) < 0.00000001; i += splitItem.FixInterval)
+ {
+ ++count;
+ }
+
+ data.Interval = splitItem.FixInterval;
+ data.Max = fixMax;
+ data.Min = fixMin;
+ data.Count = count;
+
+ return true;
+ }
+}
+
+function FrameSplitKLineX()
+{
+ this.newMethod = IFrameSplitOperator; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.ShowText = true; //是否显示坐标信息
+ this.MinDistance = 12; //刻度间隔
+ this.Period; //周期
+ this.Symbol; //股票代码
+ this.MinTextDistance = 50;
+
+ this.SplitDateTime = function () //根据时间分割
+ {
+ this.Frame.VerticalInfo = [];
+ var itemWidth = this.Frame.DistanceWidth + this.Frame.DataWidth;
+ var xOffset = this.Frame.Data.DataOffset;
+ var xPointCount = this.Frame.XPointCount;
+ var lastYear = null, lastMonth = null;
+ var textDistance = 0;
+
+ for (var i = 0, index = xOffset; i < xPointCount && index < this.Frame.Data.Data.length; ++i, ++index)
+ {
+ textDistance += itemWidth;
+ var infoData = null;
+ if (i == 0)
+ {
+ var date = IFrameSplitOperator.FormatDateString(this.Frame.Data.Data[index].Date, 'MM-DD');
+ infoData = { Value: index - xOffset, Text: date };
+ }
+ else if (textDistance > this.MinTextDistance)
+ {
+ var time = IFrameSplitOperator.FormatTimeString(this.Frame.Data.Data[index].Time);
+ infoData = { Value: index - xOffset, Text: time };
+ }
+
+ if (infoData)
+ {
+ var info = new CoordinateInfo();
+ info.Value = infoData.Value;
+ if (this.ShowText) info.Message[0] = infoData.Text;
+ if (info.Value==0) info.LineType=-1; //第1个分割线不画
+ this.Frame.VerticalInfo.push(info);
+ textDistance = 0;
+ if (i == 0) textDistance = -(this.MinTextDistance / 2);
+ }
+ }
+ }
+
+ this.SplitSecond = function () //根据时间分割
+ {
+ this.Frame.VerticalInfo = [];
+ var itemWidth = this.Frame.DistanceWidth + this.Frame.DataWidth;
+ var xOffset = this.Frame.Data.DataOffset;
+ var xPointCount = this.Frame.XPointCount;
+ var lastYear = null, lastMonth = null;
+ var textDistance = 0;
+
+ for (var i = 0, index = xOffset; i < xPointCount && index < this.Frame.Data.Data.length; ++i, ++index)
+ {
+ textDistance += itemWidth;
+ var infoData = null;
+ if (i == 0)
+ {
+ var date = IFrameSplitOperator.FormatDateString(this.Frame.Data.Data[index].Date, 'MM-DD');
+ infoData = { Value: index - xOffset, Text: date };
+ }
+ else if (textDistance > this.MinTextDistance)
+ {
+ var time = IFrameSplitOperator.FormatTimeString(this.Frame.Data.Data[index].Time,"HH:MM:SS");
+ infoData = { Value: index - xOffset, Text: time };
+ }
+
+ if (infoData)
+ {
+ var info = new CoordinateInfo();
+ info.Value = infoData.Value;
+ if (this.ShowText) info.Message[0] = infoData.Text;
+ this.Frame.VerticalInfo.push(info);
+ textDistance = 0;
+ if (i == 0) textDistance = -(this.MinTextDistance / 2);
+ }
+ }
+ }
+
+ this.SplitDate = function () //根据日期分割
+ {
+ this.Frame.VerticalInfo = [];
+ var xOffset = this.Frame.Data.DataOffset;
+ var xPointCount = this.Frame.XPointCount;
+ var lastYear = null, lastMonth = null;
+ var monthCount=0;
+
+ for (var i = 0, index = xOffset, distance = this.MinDistance; i < xPointCount && index < this.Frame.Data.Data.length; ++i, ++index)
+ {
+ var year = parseInt(this.Frame.Data.Data[index].Date / 10000);
+ var month = parseInt(this.Frame.Data.Data[index].Date / 100) % 100;
+ if (lastMonth != month) ++monthCount;
+
+ if ((distance < this.MinDistance && lastYear == year) ||
+ (lastYear != null && lastYear == year && lastMonth != null && lastMonth == month))
+ {
+ lastMonth = month;
+ ++distance;
+ continue;
+ }
+
+ var info = new CoordinateInfo();
+ info.Value = index - xOffset;
+ //info.TextColor = "rgb(51,51,51)";
+ var text;
+ if (lastYear == null || lastYear != year)
+ {
+ text = year.toString();
+ }
+ else if (lastMonth == null || lastMonth != month)
+ {
+ text = month.toString() + "月";
+ }
+
+ lastYear = year;
+ lastMonth = month;
+
+ if (this.ShowText) info.Message[0] = text;
+ if (info.Value==0) info.LineType=-1; //第1个分割线不画
+
+ this.Frame.VerticalInfo.push(info);
+ distance = 0;
+ }
+
+ if (this.Period == 0 && monthCount <= 2)
+ this.SplitShortDate();
+ }
+
+ //分隔在2个月一下的格式
+ this.SplitShortDate = function ()
+ {
+ this.Frame.VerticalInfo = [];
+ var xOffset = this.Frame.Data.DataOffset;
+ var xPointCount = this.Frame.XPointCount;
+ var minDistance = 12;
+ var isFirstYear = true;
+ for (var i = 0, index = xOffset, distance = minDistance; i < xPointCount && index < this.Frame.Data.Data.length; ++i, ++index) {
+ var year = parseInt(this.Frame.Data.Data[index].Date / 10000);
+ //var month=parseInt(this.Frame.Data.Data[index].Date/100)%100;
+ //var day=parseInt(this.Frame.Data.Data[index].Date%100);
+
+ if (distance < minDistance)
+ {
+ ++distance;
+ continue;
+ }
+
+ var info = new CoordinateInfo();
+ info.Value = index - xOffset;
+ var text;
+ if (isFirstYear)
+ {
+ text = year.toString();
+ isFirstYear = false;
+ }
+ else
+ {
+ text = IFrameSplitOperator.FormatDateString(this.Frame.Data.Data[index].Date, 'MM-DD');
+ }
+
+ if (this.ShowText) info.Message[0] = text;
+ if (info.Value==0) info.LineType=-1; //第1个分割线不画
+
+ this.Frame.VerticalInfo.push(info);
+ distance = 0;
+ }
+ }
+
+ this.Operator = function ()
+ {
+ if (this.Frame.Data == null) return;
+ if (FrameSplitKLineX.SplitCustom) FrameSplitKLineX.SplitCustom(this); //自定义分割
+ else if (ChartData.IsMinutePeriod(this.Period, true)) this.SplitDateTime();
+ else if (ChartData.IsSecondPeriod(this.Period)) this.SplitSecond();
+ else this.SplitDate();
+ }
+
+ this.CreateCoordinateInfo=function()
+ {
+ return new CoordinateInfo(); //创建一个节点坐标
+ }
+}
+
+//FrameSplitKLineX.SplitCustom=function(split) { }
+
+function FrameSplitMinutePriceY()
+{
+ this.newMethod = IFrameSplitOperator; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.High = null; //最高最低价
+ this.Low = null;
+
+ this.YClose; //昨收
+ this.Data; //分钟数据
+ this.AverageData; //分钟均线数据
+ this.OverlayChartPaint;
+ this.SplitCount = 7;
+ this.Symbol;
+ this.SplitType=0; //0=默认根据最大最小值分割 1=涨跌停分割 2=数据最大最大值分割
+ this.LimitPrice; //{Max: Min:} 涨跌停价
+ this.Custom;
+
+ this.Operator = function ()
+ {
+ this.Frame.HorizontalInfo = [];
+ this.Frame.CustomHorizontalInfo = [];
+ if (!this.Data) return;
+
+ var range=this.GetMaxMin();
+
+ if (this.Symbol && MARKET_SUFFIX_NAME.IsUSA(this.Symbol.toUpperCase()))
+ {
+ this.USASplit(range);
+ }
+ else if (this.SplitType==2)
+ {
+ this.USASplit(range);
+ }
+ else
+ {
+ this.DefaultSplit(range);
+ }
+
+ this.CustomCoordinate();
+
+ if (this.GetEventCallback)
+ {
+ var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_SPLIT_YCOORDINATE);
+ if (event && event.Callback)
+ {
+ var data={ID:this.Frame.Identify, Frame:this.Frame };
+ event.Callback(event,data,this);
+ }
+ }
+ }
+
+ this.GetMaxMin = function () //计算图中所有的数据的最大最小值
+ {
+ var max = this.YClose;
+ var min = this.YClose;
+
+ for (var i in this.Data.Data)
+ {
+ if (!this.Data.Data[i]) continue; //价格必须大于0
+ if (max < this.Data.Data[i]) max = this.Data.Data[i];
+ if (min > this.Data.Data[i]) min = this.Data.Data[i];
+ }
+
+ if (this.AverageData)
+ {
+ for (var i in this.AverageData.Data)
+ {
+ if (!this.AverageData.Data[i]) continue; //价格必须大于0
+ if (max < this.AverageData.Data[i]) max = this.AverageData.Data[i];
+ if (min > this.AverageData.Data[i]) min = this.AverageData.Data[i];
+ }
+ }
+
+ if (this.OverlayChartPaint && this.OverlayChartPaint.length > 0 && this.OverlayChartPaint[0] && this.OverlayChartPaint[0].Symbol)
+ {
+ var range = this.OverlayChartPaint[0].GetMaxMin();
+ if (range.Max && range.Max > max) max = range.Max;
+ if (range.Min && range.Min < min) min = range.Min;
+ }
+
+ if (this.SplitType==1 && this.LimitPrice)
+ {
+ if (maxthis.LimitPrice.Min) min=this.LimitPrice.Min;
+ }
+
+ if (IFrameSplitOperator.IsNumber(this.High) && IFrameSplitOperator.IsNumber(this.Low))
+ {
+ if (max < this.High) max = this.High;
+ if (min > this.Low) min = this.Low;
+ }
+
+ return { Max: max, Min: min };
+ }
+
+ this.USASplit=function(range)
+ {
+ var max=range.Max;
+ var min=range.Min;
+
+ if (max==min)
+ {
+ max=max+max*0.1;
+ min=min-min*0.1;
+ }
+ else
+ {
+ var height=this.Frame.ChartBorder.GetHeight(); //画布的高度
+ var spacePrice=5*(max-min)/height;
+ max+=spacePrice;
+ min-=spacePrice;
+ if (min<0) min=range.Min;
+ }
+
+ var showCount=this.SplitCount;
+ var distance=(max-min)/(showCount-1);
+ const minDistance=[1, 0.1, 0.01, 0.001, 0.0001];
+ var defaultfloatPrecision=JSCommonCoordinateData.GetfloatPrecision(this.Symbol);
+ if (distance0) coordinate.TextColor=g_JSChartResource.UpTextColor;
+ else if (per<0) coordinate.TextColor=g_JSChartResource.DownTextColor;
+ if (this.IsShowRightText)
+ {
+ if (this.RightTextFormat==1) coordinate.Message[1]=strPrice;
+ else coordinate.Message[1]=IFrameSplitOperator.FormatValueString(per,2)+'%'; //百分比
+ }
+ }
+
+ this.Frame.HorizontalInfo.push(coordinate);
+ }
+
+ if (this.YClose>min && this.YClose 0) this.Frame.HorizontalInfo[i].TextColor = g_JSChartResource.UpTextColor;
+ else if (per < 0) this.Frame.HorizontalInfo[i].TextColor = g_JSChartResource.DownTextColor;
+ this.Frame.HorizontalInfo[i].Message[1] = IFrameSplitOperator.FormatValueString(per, 2) + '%'; //百分比
+ }
+ }
+
+ this.Frame.HorizontalMax = max;
+ this.Frame.HorizontalMin = min;
+ }
+
+ this.CustomCoordinate = function () //自定义刻度
+ {
+ if (!this.Custom) return;
+
+ for (var i in this.Custom)
+ {
+ var item = this.Custom[i];
+ if (item.Type == 1)
+ this.CustomFixedCoordinate(item);
+ else if (item.Type==0)
+ {
+ var defaultfloatPrecision = JSCommonCoordinateData.GetfloatPrecision(this.Symbol);
+ var latestItem = this.GetLatestPrice(defaultfloatPrecision, item);
+ if (latestItem) this.Frame.CustomHorizontalInfo.push(latestItem);
+ }
+ }
+ }
+
+ this.GetLatestPrice = function (floatPrecision, option)
+ {
+ if (!this.Data || !this.Data.Data) return null;
+ if (this.Data.Data.length <= 0) return null;
+ var price = this.Data.Data[this.Data.Data.length - 1];
+ if (!IFrameSplitOperator.IsNumber(price) || !IFrameSplitOperator.IsNumber(this.YClose)) return null;
+
+ var info = new CoordinateInfo();
+ info.Type = 0;
+ info.Value = price;
+ info.TextColor = g_JSChartResource.FrameLatestPrice.TextColor;
+ info.LineType = 2; //虚线
+ if (option.Position == 'left') info.Message[0] = price.toFixed(floatPrecision);
+ else info.Message[1] = price.toFixed(floatPrecision);
+ if (price > this.YClose) info.LineColor = g_JSChartResource.FrameLatestPrice.UpBarColor;
+ else if (price < this.YClose) info.LineColor = g_JSChartResource.FrameLatestPrice.DownBarColor;
+ else info.LineColor = g_JSChartResource.FrameLatestPrice.UnchagneBarColor;
+
+ if (IFrameSplitOperator.IsNumber(option.LineType)) info.LineType=option.LineType;
+ if (option.IsShowLine == false) info.LineType = -1;
+
+ return info;
+ }
+
+ this.CustomFixedCoordinate = function (option) //固定坐标刻度
+ {
+ var defaultfloatPrecision = JSCommonCoordinateData.GetfloatPrecision(this.Symbol);
+ for (var i in option.Data)
+ {
+ var item = option.Data[i];
+ var info = new CoordinateInfo();
+ info.Type = 1;
+ info.TextColor = item.TextColor;
+ info.LineColor = item.Color;
+ info.LineType = 2; //虚线
+ if (IFrameSplitOperator.IsNumber(option.LineType)) info.LineType=option.LineType;
+ if (option.IsShowLine == false) info.LineType = -1;
+
+ if (IFrameSplitOperator.IsNumber(item.Increase)) //涨幅计算价格
+ {
+ if (!IFrameSplitOperator.IsNumber(this.YClose)) conintue;
+ info.Value = this.YClose * (1 + item.Increase);
+ }
+ else
+ {
+ info.Value = item.Value;
+ }
+
+ var text;
+ if (item.Text) text = item.Text;
+ else text = info.Value.toFixed(defaultfloatPrecision);
+ if (option.Position == 'left') info.Message[0] = text;
+ else info.Message[1] = text;
+
+ this.Frame.CustomHorizontalInfo.push(info);
+ }
+ }
+
+}
+
+function FrameSplitMinuteX()
+{
+ this.newMethod = IFrameSplitOperator; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.ShowText = true; //是否显示坐标信息
+ this.Symbol = null; //股票代码 x轴刻度根据股票类型来调整
+ this.DayCount = 1;
+ this.DayData;
+
+ this.Operator = function ()
+ {
+ this.Frame.VerticalInfo = [];
+ var xPointCount = this.Frame.XPointCount;
+ var width = this.Frame.ChartBorder.GetWidth();
+ var isHScreen = (this.Frame.IsHScreen === true);
+ if (isHScreen) width = this.Frame.ChartBorder.GetHeight();
+
+ const minuteCoordinate = JSCommonCoordinateData.MinuteCoordinateData;
+ var xcoordinateData = minuteCoordinate.GetCoordinateData(this.Symbol, width);
+ var minuteCount = xcoordinateData.Count;
+ var minuteMiddleCount = xcoordinateData.MiddleCount > 0 ? xcoordinateData.MiddleCount : parseInt(minuteCount / 2);;
+
+ var xcoordinate = xcoordinateData.Data;
+ this.Frame.XPointCount = 243;
+
+ this.Frame.XPointCount = minuteCount * this.DayCount;
+ this.Frame.MinuteCount = minuteCount;
+ this.Frame.VerticalInfo = [];
+
+ if (this.DayCount <= 1)
+ {
+ for (var i in xcoordinate)
+ {
+ var info = new CoordinateInfo();
+ //info.TextColor = "rgb(51,51,51)";
+ info.Value = xcoordinate[i][0];
+ if (this.ShowText)
+ info.Message[0] = xcoordinate[i][3];
+ this.Frame.VerticalInfo[i] = info;
+ }
+ }
+ else
+ {
+ for (var i = this.DayData.length - 1, j = 0; i >= 0; --i, ++j)
+ {
+ var info = new CoordinateInfo();
+ info.Value = j * minuteCount + minuteMiddleCount;
+ info.LineType = -1;
+ if (this.ShowText) info.Message[0] = IFrameSplitOperator.FormatDateString(this.DayData[i].Date, 'MM-DD');
+ this.Frame.VerticalInfo.push(info);
+
+ var info = new CoordinateInfo();
+ info.Value = (j + 1) * minuteCount;
+ this.Frame.VerticalInfo.push(info);
+ }
+ }
+ }
+}
+
+function FrameSplitXData()
+{
+ this.newMethod = IFrameSplitOperator; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.ShowText = true; //是否显示坐标信息
+
+ this.Operator = function ()
+ {
+ if (this.Frame.Data == null || this.Frame.XData == null) return;
+ this.Frame.VerticalInfo = [];
+ var xOffset = this.Frame.Data.DataOffset;
+ var xPointCount = this.Frame.XPointCount;
+
+ for (var i = 0, index = xOffset; i < xPointCount && index < this.Frame.Data.Data.length; ++i, ++index)
+ {
+ var info = new CoordinateInfo();
+ info.Value = index - xOffset;
+
+ if (this.ShowText)
+ info.Message[0] = this.Frame.XData[i];
+
+ this.Frame.VerticalInfo.push(info);
+ }
+ }
+}
+
+//深度图X轴价格信息
+function FrameSplitXDepth()
+{
+ this.newMethod=IFrameSplitOperator; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.ShowText=true; //是否显示坐标信息
+ this.SplitCount=3;
+ this.Symbol;
+ this.LineType=3;
+
+ this.Operator=function()
+ {
+ var xRange=this.Frame.VerticalRange;
+ if (!xRange) return;
+ this.Frame.VerticalInfo=[];
+
+ var floatPrecision=2;
+ if (this.Symbol) floatPrecision=JSCommonCoordinateData.GetfloatPrecision(this.Symbol);
+ var xMax=xRange.Max;
+ var xMin=xRange.Min;
+ if (xRange.Bid)
+ {
+ var interval=(xRange.Bid.Max-xMin)/this.SplitCount;
+ for(var i=0;i item[0] && interval <= item[1]) {
+ var result = {};
+ result.FixInterval = item[2];
+ result.Increase = item[3];
+ return result;
+ }
+ }
+
+ return null;
+ }
+}
+
+function PriceSplitData() {
+ this.newMethod = SplitData; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.Data = [
+ [0.000001, 0.000002, 0.000001, 0.0000001],
+ [0.000002, 0.000004, 0.000002, 0.0000002],
+ [0.000004, 0.000005, 0.000004, 0.0000001],
+ [0.000005, 0.00001, 0.000005, 0.0000005],
+
+ [0.00001, 0.00002, 0.00001, 0.000001],
+ [0.00002, 0.00004, 0.00002, 0.000002],
+ [0.00004, 0.00005, 0.00004, 0.000001],
+ [0.00005, 0.0001, 0.00005, 0.000005],
+
+ [0.0001, 0.0002, 0.0001, 0.00001],
+ [0.0002, 0.0004, 0.0002, 0.00002],
+ [0.0004, 0.0005, 0.0004, 0.00001],
+ [0.0005, 0.001, 0.0005, 0.00005],
+
+ [0.001, 0.002, 0.001, 0.0001],
+ [0.002, 0.004, 0.002, 0.0002],
+ [0.004, 0.005, 0.004, 0.0001],
+ [0.005, 0.01, 0.005, 0.0005],
+
+ [0.01, 0.02, 0.01, 0.001],
+ [0.02, 0.04, 0.02, 0.002],
+ [0.04, 0.05, 0.04, 0.001],
+ [0.05, 0.1, 0.05, 0.005],
+
+ [0.1, 0.2, 0.1, 0.01],
+ [0.2, 0.4, 0.2, 0.02],
+ [0.4, 0.5, 0.2, 0.01],
+ [0.5, 0.8, 0.2, 0.05],
+ [0.8, 1, 0.5, 0.05],
+
+ [1, 2, 0.5, 0.05],
+ [2, 4, 0.5, 0.05],
+ [4, 5, 0.5, 0.05],
+ [5, 10, 0.5, 0.05],
+
+ [10, 12, 10, 2],
+ [20, 40, 20, 5],
+ [40, 50, 40, 2],
+ [50, 100, 50, 10],
+
+ [100, 200, 100, 10],
+ [200, 400, 200, 20],
+ [400, 500, 400, 10],
+ [500, 1000, 500, 50],
+
+ [1000, 2000, 1000, 50],
+ [2000, 4000, 2000, 50],
+ [4000, 5000, 4000, 50],
+ [5000, 10000, 5000, 100],
+
+ [10000, 20000, 10000, 1000],
+ [20000, 40000, 20000, 2000],
+ [40000, 50000, 40000, 1000],
+ [50000, 100000, 50000, 5000],
+
+ [100000, 200000, 100000, 10000],
+ [200000, 400000, 200000, 20000],
+ [400000, 500000, 400000, 10000],
+ [500000, 1000000, 500000, 50000],
+
+ [1000000, 2000000, 1000000, 100000],
+ [2000000, 4000000, 2000000, 200000],
+ [4000000, 5000000, 4000000, 100000],
+ [5000000, 10000000, 5000000, 500000],
+
+ [10000000, 20000000, 10000000, 1000000],
+ [20000000, 40000000, 20000000, 2000000],
+ [40000000, 50000000, 40000000, 1000000],
+ [50000000, 100000000, 50000000, 5000000],
+
+ [100000000, 200000000, 100000000, 10000000],
+ [200000000, 400000000, 200000000, 20000000],
+ [400000000, 500000000, 400000000, 10000000],
+ [500000000, 1000000000, 500000000, 50000000],
+
+ [1000000000, 2000000000, 1000000000, 100000000],
+ [2000000000, 4000000000, 2000000000, 200000000],
+ [4000000000, 5000000000, 4000000000, 100000000],
+ [5000000000, 10000000000, 5000000000, 500000000],
+ ];
+}
+
+//整数分割
+function IntegerSplitData() {
+ this.newMethod = SplitData; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.Data =
+ [
+ [0.000001, 0.000002, 0.000001, 0.0000001],
+ [0.000002, 0.000004, 0.000002, 0.0000002],
+ [0.000004, 0.000005, 0.000004, 0.0000001],
+ [0.000005, 0.00001, 0.000005, 0.0000005],
+
+ [0.00001, 0.00002, 0.00001, 0.000001],
+ [0.00002, 0.00004, 0.00002, 0.000002],
+ [0.00004, 0.00005, 0.00004, 0.000001],
+ [0.00005, 0.0001, 0.00005, 0.000005],
+
+ [0.0001, 0.0002, 0.0001, 0.00001],
+ [0.0002, 0.0004, 0.0002, 0.00002],
+ [0.0004, 0.0005, 0.0004, 0.00001],
+ [0.0005, 0.001, 0.0005, 0.00005],
+
+ [0.001, 0.002, 0.001, 0.0001],
+ [0.002, 0.004, 0.002, 0.0002],
+ [0.004, 0.005, 0.004, 0.0001],
+ [0.005, 0.01, 0.005, 0.0005],
+
+ [0.01, 0.02, 0.01, 0.001],
+ [0.02, 0.04, 0.02, 0.002],
+ [0.04, 0.05, 0.04, 0.001],
+ [0.05, 0.1, 0.05, 0.005],
+
+ [0.1, 0.2, 1, 1],
+ [0.2, 0.4, 1, 1],
+ [0.4, 0.5, 1, 1],
+ [0.5, 0.8, 1, 1],
+ [0.8, 1, 1, 1],
+
+ [1, 2, 1, 1],
+ [2, 4, 2, 1],
+ [4, 5, 4, 1],
+ [5, 10, 5, 1],
+
+ [10, 12, 10, 2],
+ [20, 40, 20, 5],
+ [40, 50, 40, 2],
+ [50, 100, 50, 10],
+
+ [100, 200, 100, 10],
+ [200, 400, 200, 20],
+ [400, 500, 400, 10],
+ [500, 1000, 500, 50],
+
+ [1000, 2000, 1000, 50],
+ [2000, 4000, 2000, 50],
+ [4000, 5000, 4000, 50],
+ [5000, 10000, 5000, 100],
+
+ [10000, 20000, 10000, 1000],
+ [20000, 40000, 20000, 2000],
+ [40000, 50000, 40000, 1000],
+ [50000, 100000, 50000, 5000],
+
+ [100000, 200000, 100000, 10000],
+ [200000, 400000, 200000, 20000],
+ [400000, 500000, 400000, 10000],
+ [500000, 1000000, 500000, 50000],
+
+ [1000000, 2000000, 1000000, 100000],
+ [2000000, 4000000, 2000000, 200000],
+ [4000000, 5000000, 4000000, 100000],
+ [5000000, 10000000, 5000000, 500000],
+
+ [10000000, 20000000, 10000000, 1000000],
+ [20000000, 40000000, 20000000, 2000000],
+ [40000000, 50000000, 40000000, 1000000],
+ [50000000, 100000000, 50000000, 5000000],
+
+ [100000000, 200000000, 100000000, 10000000],
+ [200000000, 400000000, 200000000, 20000000],
+ [400000000, 500000000, 400000000, 10000000],
+ [500000000, 1000000000, 500000000, 50000000],
+
+ [1000000000, 2000000000, 1000000000, 100000000],
+ [2000000000, 4000000000, 2000000000, 200000000],
+ [4000000000, 5000000000, 4000000000, 100000000],
+ [5000000000, 10000000000, 5000000000, 500000000],
+ ];
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////
+//
+function IChangeStringFormat() {
+ this.Data;
+ this.Value; //数据
+ this.Text; //输出字符串
+
+ this.Operator = function () {
+ return false;
+ }
+ }
+
+
+ function HQPriceStringFormat()
+ {
+ this.newMethod = IChangeStringFormat; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.Symbol;
+ this.FrameID;
+ this.LanguageID = JSCHART_LANGUAGE_ID.LANGUAGE_CHINESE_ID;
+ this.PercentageText; //百分比
+ this.RValue; //右边值
+ this.RText;
+
+ this.Operator = function ()
+ {
+ this.RText = null;
+ if (IFrameSplitOperator.IsString(this.RValue)) this.RText = this.RValue;
+ if (!this.Value) return false;
+
+ var defaultfloatPrecision = 2; //价格小数位数
+ if (this.FrameID == 0) //第1个窗口显示原始价格
+ {
+ var defaultfloatPrecision = JSCommonCoordinateData.GetfloatPrecision(this.Symbol);
+ this.Text = this.Value.toFixed(defaultfloatPrecision);
+ }
+ else
+ {
+ this.Text = IFrameSplitOperator.FormatValueString(this.Value, defaultfloatPrecision, this.LanguageID);
+ }
+
+ return true;
+ }
+ }
+
+ function HQDateStringFormat()
+ {
+ this.newMethod = IChangeStringFormat; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.DateFormatType=0; //0=YYYY-MM-DD 1=YYYY/MM/DD 2=YYYY/MM/DD/W 3=DD/MM/YYYY
+ this.LanguageID=0;
+
+ this.Operator = function ()
+ {
+ if (!IFrameSplitOperator.IsNumber(this.Value) || this.Value<0) return false;
+ if (!this.Data) return false;
+
+ var index = this.Value;
+ index = parseInt(index.toFixed(0));
+ if (this.Data.DataOffset + index >= this.Data.Data.length) return false;
+
+ var currentData = this.Data.Data[this.Data.DataOffset + index];
+ var date = currentData.Date;
+ var dateFormatString="YYYY-MM-DD";
+ if (this.DateFormatType==1) dateFormatString="YYYY/MM/DD";
+ else if (this.DateFormatType==2) dateFormatString="YYYY/MM/DD/W";
+ else if (this.DateFormatType==3) dateFormatString="DD/MM/YYYY";
+ this.Text = IFrameSplitOperator.FormatDateString(date,dateFormatString,this.LanguageID);
+ if (ChartData.IsMinutePeriod(this.Data.Period, true)) // 分钟周期
+ {
+ var time = IFrameSplitOperator.FormatTimeString(currentData.Time);
+ this.Text = this.Text + " " + time;
+ }
+ else if (ChartData.IsSecondPeriod(this.Data.Period))
+ {
+ var time = IFrameSplitOperator.FormatTimeString(currentData.Time,"HH:MM:SS");
+ this.Text = this.Text + " " + time;
+ }
+
+ return true;
+ }
+ }
+
+ function HQMinuteTimeStringFormat()
+ {
+ this.newMethod = IChangeStringFormat; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.Frame;
+ this.Symbol;
+
+ this.Operator = function ()
+ {
+ if (this.Value == null || isNaN(this.Value)) return false;
+
+ var index = Math.abs(this.Value);
+ index = parseInt(index.toFixed(0));
+ var showIndex = index;
+ if (this.Frame && this.Frame.MinuteCount) showIndex = index % this.Frame.MinuteCount;
+
+ var timeStringData = JSCommonCoordinateData.MinuteTimeStringData;
+ var timeData = timeStringData.GetTimeData(this.Symbol);
+ if (!timeData) return false;
+
+ if (showIndex < 0) showIndex = 0;
+ else if (showIndex > timeData.length) showIndex = timeData.length - 1;
+ if (this.Frame && index >= this.Frame.XPointCount)
+ showIndex = timeData.length - 1;
+
+ var time = timeData[showIndex];
+ this.Text = IFrameSplitOperator.FormatTimeString(time);
+ return true;
+ }
+ }
+
+ function DivTooltipDataForamt()
+ {
+ this.DataMap=new Map(
+ [
+ ["CorssCursor_XStringFormat", { Create:function() { return new HQDateStringFormat(); } }],
+ ["CorssCursor_YStringFormat", { Create:function() { return new HQPriceStringFormat(); } }]
+ ]
+ );
+
+ this.Create=function(name)
+ {
+ if (!this.DataMap.has(name)) return null;
+ var item=this.DataMap.get(name);
+ return item.Create();
+ }
+ }
+
+ var g_DivTooltipDataForamt=new DivTooltipDataForamt();
+
+
+//导出统一使用JSCommon命名空间名
+module.exports =
+{
+ JSCommonSplit:
+ {
+ CoordinateInfo: CoordinateInfo,
+ IFrameSplitOperator: IFrameSplitOperator,
+ FrameSplitKLinePriceY: FrameSplitKLinePriceY,
+ FrameSplitY: FrameSplitY,
+ FrameSplitKLineX: FrameSplitKLineX,
+ FrameSplitMinutePriceY: FrameSplitMinutePriceY,
+ FrameSplitMinuteX: FrameSplitMinuteX,
+ FrameSplitXData: FrameSplitXData,
+ SplitData: SplitData,
+ PriceSplitData: PriceSplitData,
+ FrameSplitXDepth:FrameSplitXDepth,
+ IChangeStringFormat:IChangeStringFormat,
+ HQPriceStringFormat:HQPriceStringFormat,
+ HQDateStringFormat:HQDateStringFormat,
+ HQMinuteTimeStringFormat:HQMinuteTimeStringFormat,
+ },
+
+ JSCommonSplit_CoordinateInfo: CoordinateInfo,
+ JSCommonSplit_IFrameSplitOperator: IFrameSplitOperator,
+ JSCommonSplit_FrameSplitKLinePriceY: FrameSplitKLinePriceY,
+ JSCommonSplit_FrameSplitY: FrameSplitY,
+ JSCommonSplit_FrameSplitKLineX: FrameSplitKLineX,
+ JSCommonSplit_FrameSplitMinutePriceY: FrameSplitMinutePriceY,
+ JSCommonSplit_FrameSplitMinuteX: FrameSplitMinuteX,
+ JSCommonSplit_FrameSplitXData: FrameSplitXData,
+ JSCommonSplit_SplitData: SplitData,
+ JSCommonSplit_PriceSplitData: PriceSplitData,
+ JSCommonSplit_FrameSplitXDepth:FrameSplitXDepth,
+
+ JSCommonFormat_IChangeStringFormat:IChangeStringFormat,
+ JSCommonFormat_HQPriceStringFormat:HQPriceStringFormat,
+ JSCommonFormat_HQDateStringFormat:HQDateStringFormat,
+ JSCommonFormat_HQMinuteTimeStringFormat:HQMinuteTimeStringFormat,
+ JSCommonFormat_Global_DataFormat :g_DivTooltipDataForamt,
+};
\ No newline at end of file
diff --git a/uni_modules/jones-hqchart2/js_sdk/umychart.hqIndexformula.wechat.js b/uni_modules/jones-hqchart2/js_sdk/umychart.hqIndexformula.wechat.js
new file mode 100644
index 0000000..ad123ab
--- /dev/null
+++ b/uni_modules/jones-hqchart2/js_sdk/umychart.hqIndexformula.wechat.js
@@ -0,0 +1,934 @@
+/*
+ copyright (c) 2018 jones
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ 开源项目 https://github.com/jones2000/HQChart
+
+ jones_2000@163.com
+
+ 指标计算方法 2.0 版本使用的算法
+*/
+
+function HQIndexFormula()
+{
+
+}
+
+//指数平均数指标 EMA(close,10)
+HQIndexFormula.EMA=function(data,dayCount)
+{
+ var result = [];
+
+ var offset=0;
+ if (offset>=data.length) return result;
+
+ //取首个有效数据
+ for(;offsetdata.length) return result;
+
+ var max=-10000;
+ for(var i=n,j=0;idata[max])
+ max = j;
+ }
+ }
+
+ result[i] = data[max];
+ }
+
+ return result;
+}
+
+HQIndexFormula.LLV=function(data,n)
+{
+ var result = [];
+ if (n>data.length) return result;
+
+ var min=-10000;
+
+ for(var i=n;idata[min]?min:i;
+ }
+ else
+ {
+ for(var j=(min=i-n+1)+1;j<=i;++j)
+ {
+ if(data[j]=data.length) return result;
+
+ result=data.slice(0,data.length-n);
+
+ for(var i=0;idata2比较 返回 0/1 数组
+HQIndexFormula.ARRAY_GT=function(data,data2)
+{
+ var result=[];
+ var IsNumber=typeof(data2)=="number";
+ if (IsNumber)
+ {
+ for(var i in data)
+ {
+ result[i]=(data[i]>data2 ? 1:0);
+ }
+ }
+ else
+ {
+ var count=Math.max(data.length,data2.length)
+
+ for(var i=0;idata2[i] ? 1:0;
+ else
+ result[i]=null;
+ }
+ }
+
+ return result;
+}
+
+//数组 data>=data2比较 返回 0/1 数组
+HQIndexFormula.ARRAY_GTE=function(data,data2)
+{
+ var result=[];
+ var IsNumber=typeof(data2)=="number";
+ if (IsNumber)
+ {
+ for(var i in data)
+ {
+ result[i]=(data[i]>=data2 ? 1:0);
+ }
+ }
+ else
+ {
+ var count=Math.max(data.length,data2.length)
+
+ for(var i=0;i=data2[i] ? 1:0;
+ else
+ result[i]=null;
+ }
+ }
+
+ return result;
+}
+
+//数组 data=data.length) return result;
+
+ var i=dayCount;
+ for(;i=data.length) return result;
+
+ var index=0;
+ for(;indexdata2[index]&&data[index-1]REF(CLOSE,1),VOL,-VOL);\n\
+OBV:SUM(IF(CLOSE==REF(CLOSE,1),0,VA),0);\n\
+MAOBV:MA(OBV,M);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.DMI=function()
+{
+ let data=
+ {
+ Name:'DMI', Description:'趋向指标', IsMainIndex:false,
+ Args:[ { Name:'N', Value:14}, { Name:'MM', Value:6} ],
+ Script: //脚本
+'MTR:=EXPMEMA(MAX(MAX(HIGH-LOW,ABS(HIGH-REF(CLOSE,1))),ABS(REF(CLOSE,1)-LOW)),N);\n\
+HD :=HIGH-REF(HIGH,1);\n\
+LD :=REF(LOW,1)-LOW;\n\
+DMP:=EXPMEMA(IF(HD>0&&HD>LD,HD,0),N);\n\
+DMM:=EXPMEMA(IF(LD>0&&LD>HD,LD,0),N);\n\
+PDI: DMP*100/MTR;\n\
+MDI: DMM*100/MTR;\n\
+ADX: EXPMEMA(ABS(MDI-PDI)/(MDI+PDI)*100,MM);\n\
+ADXR:EXPMEMA(ADX,MM);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.CR=function()
+{
+ let data=
+ {
+ Name:'CR', Description:'带状能量线', IsMainIndex:false,
+ Args:[ { Name:'N', Value:26}, { Name:'M1', Value:10},{ Name:'M2', Value:20},{ Name:'M3', Value:40},{ Name:'M4', Value:62} ],
+ Script: //脚本
+'MID:=REF(HIGH+LOW,1)/2;\n\
+CR:SUM(MAX(0,HIGH-MID),N)/SUM(MAX(0,MID-LOW),N)*100;\n\
+MA1:REF(MA(CR,M1),M1/2.5+1);\n\
+MA2:REF(MA(CR,M2),M2/2.5+1);\n\
+MA3:REF(MA(CR,M3),M3/2.5+1);\n\
+MA4:REF(MA(CR,M4),M4/2.5+1);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.PSY=function()
+{
+ let data=
+ {
+ Name:'PSY', Description:'心理线', IsMainIndex:false,
+ Args:[ { Name:'N', Value:12}, { Name:'M', Value:6} ],
+ Script: //脚本
+'PSY:COUNT(CLOSE>REF(CLOSE,1),N)/N*100;\r\
+PSYMA:MA(PSY,M);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.CCI=function()
+{
+ let data=
+ {
+ Name:'CCI', Description:'商品路径指标', IsMainIndex:false,
+ Args:[ { Name:'N', Value:14} ],
+ Script: //脚本
+'TYP:=(HIGH+LOW+CLOSE)/3;\n\
+CCI:(TYP-MA(TYP,N))/(0.015*AVEDEV(TYP,N));'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.DMA=function()
+{
+ let data=
+ {
+ Name:'DMA', Description:'平均差', IsMainIndex:false,
+ Args:[ { Name:'N1', Value:10},{ Name:'N2', Value:50},{ Name:'M', Value:10} ],
+ Script: //脚本
+'DIF:MA(CLOSE,N1)-MA(CLOSE,N2);\n\
+DIFMA:MA(DIF,M);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.TRIX=function()
+{
+ let data=
+ {
+ Name:'TRIX', Description:'三重指数平均线', IsMainIndex:false,
+ Args:[ { Name:'N', Value:12},{ Name:'M', Value:9} ],
+ Script: //脚本
+'MTR:=EMA(EMA(EMA(CLOSE,N),N),N);\n\
+TRIX:(MTR-REF(MTR,1))/REF(MTR,1)*100;\n\
+MATRIX:MA(TRIX,M) ;'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.VR=function()
+{
+ let data=
+ {
+ Name:'VR', Description:'成交量变异率', IsMainIndex:false,
+ Args:[ { Name:'N', Value:26},{ Name:'M', Value:6} ],
+ Script: //脚本
+'TH:=SUM(IF(CLOSE>REF(CLOSE,1),VOL,0),N);\n\
+TL:=SUM(IF(CLOSE[REF(CLOSE,1),MIDA,MIDB),0);\n\
+MAWAD:MA(WAD,M);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.CHO=function()
+{
+ let data=
+ {
+ Name:'CHO', Description:'佳庆指标', IsMainIndex:false,
+ Args:[ { Name:'N1', Value:10}, { Name:'N2', Value:20}, { Name:'M', Value:6}],
+ Script: //脚本
+'MID:=SUM(VOL*(2*CLOSE-HIGH-LOW)/(HIGH+LOW),0);\n\
+CHO:MA(MID,N1)-MA(MID,N2);\n\
+MACHO:MA(CHO,M);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.ADTM=function()
+{
+ let data=
+ {
+ Name:'ADTM', Description:'动态买卖气指标', IsMainIndex:false,
+ Args:[ { Name:'N', Value:23}, { Name:'M', Value:8}],
+ Script: //脚本
+'DTM:=IF(OPEN<=REF(OPEN,1),0,MAX((HIGH-OPEN),(OPEN-REF(OPEN,1))));\n\
+DBM:=IF(OPEN>=REF(OPEN,1),0,MAX((OPEN-LOW),(OPEN-REF(OPEN,1))));\n\
+STM:=SUM(DTM,N);\n\
+SBM:=SUM(DBM,N);\n\
+ADTM:IF(STM>SBM,(STM-SBM)/STM,IF(STM==SBM,0,(STM-SBM)/SBM));\n\
+MAADTM:MA(ADTM,M);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.HSL=function()
+{
+ let data=
+ {
+ Name:'HSL', Description:'换手线', IsMainIndex:false,
+ Args:[ { Name:'N', Value:5} ],
+ Script: //脚本
+'HSL:IF((SETCODE==0||SETCODE==1),100*VOL,VOL)/(FINANCE(7)/100);\n\
+MAHSL:MA(HSL,N);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.BIAS36=function()
+{
+ let data=
+ {
+ Name:'BIAS36', Description:'三六乖离', IsMainIndex:false,
+ Args:[ { Name:'M', Value:6} ],
+ Script: //脚本
+'BIAS36:MA(CLOSE,3)-MA(CLOSE,6);\n\
+BIAS612:MA(CLOSE,6)-MA(CLOSE,12);\n\
+MABIAS:MA(BIAS36,M);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.BIAS_QL=function()
+{
+ let data=
+ {
+ Name:'BIAS_QL', Description:'乖离率-传统版', IsMainIndex:false,
+ Args:[ { Name:'N', Value:6}, { Name:'M', Value:6} ],
+ Script: //脚本
+'BIAS :(CLOSE-MA(CLOSE,N))/MA(CLOSE,N)*100;\n\
+BIASMA :MA(BIAS,M);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.DPO=function()
+{
+ let data=
+ {
+ Name:'DPO', Description:'区间震荡线', IsMainIndex:false,
+ Args:[ { Name:'N', Value:20}, { Name:'M', Value:6} ],
+ Script: //脚本
+'DPO:CLOSE-REF(MA(CLOSE,N),N/2+1);\n\
+MADPO:MA(DPO,M);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.OSC=function()
+{
+ let data=
+ {
+ Name:'OSC', Description:'变动速率线', IsMainIndex:false,
+ Args:[ { Name:'N', Value:20}, { Name:'M', Value:6} ],
+ Script: //脚本
+'OSC:100*(CLOSE-MA(CLOSE,N));\n\
+MAOSC:EXPMEMA(OSC,M);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.ATR=function()
+{
+ let data=
+ {
+ Name:'ATR', Description:'真实波幅', IsMainIndex:false,
+ Args:[ { Name:'N', Value:14}],
+ Script: //脚本
+'MTR:MAX(MAX((HIGH-LOW),ABS(REF(CLOSE,1)-HIGH)),ABS(REF(CLOSE,1)-LOW));\n\
+ATR:MA(MTR,N);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.NVI=function()
+{
+ let data=
+ {
+ Name:'ATR', Description:'负成交量', IsMainIndex:false,
+ Args:[ { Name:'N', Value:72} ],
+ Script: //脚本
+'NVI:100*MULAR(IF(V][REF(V,1),C/REF(C,1),1),0);\n\
+MANVI:MA(NVI,N);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.UOS=function()
+{
+ let data=
+ {
+ Name:'UOS', Description:'终极指标', IsMainIndex:false,
+ Args:[ { Name:'N1', Value:7} ,{ Name:'N2', Value:14},{ Name:'N3', Value:28},{ Name:'M', Value:6}],
+ Script: //脚本
+'TH:=MAX(HIGH,REF(CLOSE,1));\n\
+TL:=MIN(LOW,REF(CLOSE,1));\n\
+ACC1:=SUM(CLOSE-TL,N1)/SUM(TH-TL,N1);\n\
+ACC2:=SUM(CLOSE-TL,N2)/SUM(TH-TL,N2);\n\
+ACC3:=SUM(CLOSE-TL,N3)/SUM(TH-TL,N3);\n\
+UOS:(ACC1*N2*N3+ACC2*N1*N3+ACC3*N1*N2)*100/(N1*N2+N1*N3+N2*N3);\n\
+MAUOS:EXPMEMA(UOS,M);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.CYW=function()
+{
+ let data=
+ {
+ Name:'CYW', Description:'主力控盘', IsMainIndex:false,
+ Args:[ ],
+ Script: //脚本
+'VAR1:=CLOSE-LOW;\n\
+VAR2:=HIGH-LOW;\n\
+VAR3:=CLOSE-HIGH;\n\
+VAR4:=IF(HIGH>LOW,(VAR1/VAR2+VAR3/VAR2)*VOL,0);\n\
+CYW: SUM(VAR4,10)/10000, COLORSTICK;'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.LON=function()
+{
+ let data=
+ {
+ Name:'LON', Description:'龙系长线', IsMainIndex:false,
+ Args:[ { Name:'N', Value:10} ],
+ Script: //脚本
+'LC := REF(CLOSE,1);\n\
+VID := SUM(VOL,2)/(((HHV(HIGH,2)-LLV(LOW,2)))*100);\n\
+RC := (CLOSE-LC)*VID;\n\
+LONG := SUM(RC,0);\n\
+DIFF := SMA(LONG,10,1);\n\
+DEA := SMA(LONG,20,1);\n\
+LON : DIFF-DEA;\n\
+LONMA : MA(LON,10);\n\
+LONT : LON, COLORSTICK;'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.NDB = function ()
+{
+ let data =
+ {
+ Name: 'NDB', Description: '脑电波', IsMainIndex: false,
+ Args: [{ Name: 'P1', Value: 5 }, { Name: 'P2', Value: 10 }],
+ Script: //脚本
+'HH:=IF(C/REF(C,1)>1.098 AND L>REF(H,1),2*C-REF(C,1)-H,2*C-H-L);\n\
+V1:= BARSCOUNT(C) - 1;\n\
+V2:= 2 * REF(C, V1) - REF(H, V1) - REF(L, V1);\n\
+DK: SUM(HH, 0) + V2;\n\
+MDK5: MA(DK, P1);\n\
+MDK10: MA(DK, P2);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.SKDJ = function ()
+{
+ let data =
+ {
+ Name: 'SKDJ', Description: '慢速随机指标', IsMainIndex: false,
+ Args: [{ Name: 'N', Value: 9 }, { Name: 'M', Value: 3 }],
+ Script: //脚本
+ 'LOWV:=LLV(LOW,N);\n\
+HIGHV:=HHV(HIGH,N);\n\
+RSV:=EMA((CLOSE-LOWV)/(HIGHV-LOWV)*100,M);\n\
+K:EMA(RSV,M);\n\
+D:MA(K,M);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.KD = function ()
+{
+ let data =
+ {
+ Name: 'KD', Description: '随机指标KD', IsMainIndex: false,
+ Args: [{ Name: 'N', Value: 9 }, { Name: 'M1', Value: 3 }, { Name: 'M2', Value: 3 }],
+ Script: //脚本
+ 'RSV:=(CLOSE-LLV(LOW,N))/(HHV(HIGH,N)-LLV(LOW,N))*100;\n\
+K:SMA(RSV,M1,1);\n\
+D:SMA(K,M2,1);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.FKX = function ()
+{
+ let data =
+ {
+ Name: 'FKX', Description: '反K线', IsMainIndex: true,
+ Args: [],
+ Script: //脚本
+ 'DRAWKLINE(-LOW, -OPEN, -HIGH, -CLOSE);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.DKCOL = function ()
+{
+ let data =
+ {
+ Name: 'DKCOL', Description: '多空能量柱(适用于分时主图)', IsMainIndex: true,
+ Args: [{ Name: 'N', Value: 5 }],
+ Script: //脚本
+ 'FF:=(C-REF(C,N))/REF(C,N);\n\
+STICKLINE(FF>0,DYNAINFO(3),DYNAINFO(3)*(1+FF),0.5,0),COLORRED;\n\
+STICKLINE(FF<0,DYNAINFO(3),DYNAINFO(3)*(1+FF),0.5,0),COLORGREEN;'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.UDL = function ()
+{
+ let data =
+ {
+ Name: 'UDL', Description: '引力线', IsMainIndex: false,
+ Args: [{ Name: 'N1', Value: 3 }, { Name: 'N2', Value: 5 }, { Name: 'N3', Value: 10 }, { Name: 'N4', Value: 20 }, { Name: 'M', Value: 6 }],
+ Script: //脚本
+ 'UDL:(MA(CLOSE,N1)+MA(CLOSE,N2)+MA(CLOSE,N3)+MA(CLOSE,N4))/4;\n\
+MAUDL:MA(UDL,M);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.MFI = function ()
+{
+ let data =
+ {
+ Name: 'MFI', Description: '资金流量指标', IsMainIndex: false,
+ Args: [{ Name: 'N', Value: 14 }, { Name: 'N2', Value: 6 }],
+ Script: //脚本
+ 'TYP := (HIGH + LOW + CLOSE)/3;\n\
+V1:=SUM(IF(TYP>REF(TYP,1),TYP*VOL,0),N)/SUM(IF(TYP][=0,DIF,0);\n\
+VD:=IF(DIF<0,-DIF,0);\n\
+MAU1:=MEMA(VU,M1);\n\
+MAD1:=MEMA(VD,M1);\n\
+MAU2:=MEMA(VU,M2);\n\
+MAD2:=MEMA(VD,M2);\n\
+RSI10:MA(100*MAU1/(MAU1+MAD1),M1);\n\
+RSI6:MA(100*MAU2/(MAU2+MAD2),M2);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.CYD = function ()
+{
+ let data =
+ {
+ Name: 'CYD', Description: '承接因子', IsMainIndex: false,
+ Args: [{ Name: 'N', Value: 21 }],
+ Script: //脚本
+ 'CYDS:WINNER(CLOSE)/(VOL/CAPITAL);\n\
+CYDN:WINNER(CLOSE)/MA(VOL/CAPITAL,N);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.CYF = function ()
+{
+ let data =
+ {
+ Name: 'CYF', Description: '市场能量', IsMainIndex: false,
+ Args: [{ Name: 'N', Value: 21 }],
+ Script: //脚本
+ 'CYF:100-100/(1+EMA(HSL,N));'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.TAPI = function ()
+{
+ let data =
+ {
+ Name: 'TAPI', Description: '加权指数成交值', IsMainIndex: false,
+ Args: [{ Name: 'M', Value: 6 }],
+ Script: //脚本
+ 'TAPI:AMOUNT/INDEXC;\n\
+MATAIP:MA(TAPI,M);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.VMACD = function ()
+{
+ let data =
+ {
+ Name: 'VMACD', Description: '量平滑异同平均', IsMainIndex: false,
+ Args: [{ Name: 'SHORT', Value: 12 }, { Name: 'LONG', Value: 26 }, { Name: 'MID', Value: 9 }],
+ Script: //脚本
+ 'DIF:EMA(VOL,SHORT)-EMA(VOL,LONG);\n\
+DEA:EMA(DIF,MID);\n\
+MACD:DIF-DEA,COLORSTICK;'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.QACD = function ()
+{
+ let data =
+ {
+ Name: 'QACD', Description: '快速异同平均', IsMainIndex: false,
+ Args: [{ Name: 'N1', Value: 12 }, { Name: 'N2', Value: 26 }, { Name: 'M', Value: 9 }],
+ Script: //脚本
+ 'DIF:EMA(CLOSE,N1)-EMA(CLOSE,N2);\n\
+MACD:EMA(DIF,M);\n\
+DDIF:DIF-MACD;'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.VPT = function ()
+{
+ let data =
+ {
+ Name: 'VPT', Description: '量价曲线', IsMainIndex: false,
+ Args: [{ Name: 'N', Value: 51 }, { Name: 'M', Value: 6 }],
+ Script: //脚本
+ 'VPT:SUM(VOL*(CLOSE-REF(CLOSE,1))/REF(CLOSE,1),N);\n\
+MAVPT:MA(VPT,M);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.WVAD = function ()
+{
+ let data =
+ {
+ Name: 'WVAD', Description: '威廉变异离散量', IsMainIndex: false,
+ Args: [{ Name: 'N', Value: 24 }, { Name: 'M', Value: 6 }],
+ Script: //脚本
+ 'WVAD:SUM((CLOSE-OPEN)/(HIGH-LOW)*VOL,N)/10000;\n\
+MAWVAD:MA(WVAD,M);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.DBQR = function ()
+{
+ let data =
+ {
+ Name: 'WVAD', Description: '对比强弱', IsMainIndex: false,
+ Args: [{ Name: 'N', Value: 5 }, { Name: 'M1', Value: 10 }, { Name: 'M2', Value: 20 }, { Name: 'M3', Value: 60 }],
+ Script: //脚本
+ 'ZS:(INDEXC-REF(INDEXC,N))/REF(INDEXC,N);\n\
+GG:(CLOSE-REF(CLOSE,N))/REF(CLOSE,N);\n\
+MADBQR1:MA(GG,M1);\n\
+MADBQR2:MA(GG,M2);\n\
+MADBQR3:MA(GG,M3);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.JS = function ()
+{
+ let data =
+ {
+ Name: 'JS', Description: '加速线', IsMainIndex: false,
+ Args: [{ Name: 'N', Value: 5 }, { Name: 'M1', Value: 5 }, { Name: 'M2', Value: 10 }, { Name: 'M3', Value: 20 }],
+ Script: //脚本
+ 'JS:100*(CLOSE-REF(CLOSE,N))/(N*REF(CLOSE,N));\n\
+MAJS1:MA(JS,M1);\n\
+MAJS2:MA(JS,M2);\n\
+MAJS3:MA(JS,M3);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.CYE = function ()
+{
+ let data =
+ {
+ Name: 'CYE', Description: '市场趋势', IsMainIndex: false,
+ Args: [],
+ Script: //脚本
+ 'MAL:=MA(CLOSE,5);\n\
+MAS:=MA(MA(CLOSE,20),5);\n\
+CYEL:(MAL-REF(MAL,1))/REF(MAL,1)*100;\n\
+CYES:(MAS-REF(MAS,1))/REF(MAS,1)*100;'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.QR = function ()
+{
+ let data =
+ {
+ Name: 'QR', Description: '强弱指标', IsMainIndex: false,
+ Args: [{ Name: 'N', Value: 21 }],
+ Script: //脚本
+ '个股: (CLOSE-REF(CLOSE,N))/REF(CLOSE,N)*100; \n\
+大盘: (INDEXC-REF(INDEXC,N))/REF(INDEXC,N)*100; \n\
+强弱值:EMA(个股-大盘,2),COLORSTICK;'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.GDX = function ()
+{
+ let data =
+ {
+ Name: 'GDX', Description: '轨道线', IsMainIndex: false,
+ Args: [{ Name: 'N', Value: 30 }, { Name: 'M', Value: 9 }],
+ Script: //脚本
+ 'AA:=ABS((2*CLOSE+HIGH+LOW)/4-MA(CLOSE,N))/MA(CLOSE,N); \n\
+轨道:DMA(CLOSE,AA);\n\
+压力线:(1+M/100)*轨道; \n\
+支撑线:(1-M/100)*轨道;'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.JLHB = function ()
+{
+ let data =
+ {
+ Name: 'JLHB', Description: '绝路航标', IsMainIndex: false,
+ Args: [{ Name: 'N', Value: 7 }, { Name: 'M', Value: 5 }],
+ Script: //脚本
+ 'VAR1:=(CLOSE-LLV(LOW,60))/(HHV(HIGH,60)-LLV(LOW,60))*80; \n\
+B:SMA(VAR1,N,1); \n\
+VAR2:SMA(B,M,1); \n\
+绝路航标:IF(CROSS(B,VAR2) AND B<40,50,0);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.PCNT = function ()
+{
+ let data =
+ {
+ Name: 'PCNT', Description: '幅度比', IsMainIndex: false,
+ Args: [{ Name: 'M', Value: 5 }],
+ Script: //脚本
+ 'PCNT:(CLOSE-REF(CLOSE,1))/CLOSE*100;\n\
+MAPCNT:EXPMEMA(PCNT,M);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.AMO = function ()
+{
+ let data =
+ {
+ Name: 'AMO', Description: '成交金额', IsMainIndex: false,
+ Args: [{ Name: 'M1', Value: 5 }, { Name: 'M2', Value: 10 }],
+ Script: //脚本
+ 'AMOW:AMOUNT/10000.0,VOLSTICK;\n\
+AMO1:MA(AMOW,M1);\n\
+AMO2:MA(AMOW,M2);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.VRSI = function ()
+{
+ let data =
+ {
+ Name: 'VRSI', Description: '相对强弱量', IsMainIndex: false,
+ Args: [{ Name: 'N1', Value: 6 }, { Name: 'N2', Value: 12 }, { Name: 'N3', Value: 24 }],
+ Script: //脚本
+ 'LC:=REF(VOL,1);\n\
+RSI1:SMA(MAX(VOL-LC,0),N1,1)/SMA(ABS(VOL-LC),N1,1)*100;\n\
+RSI2:SMA(MAX(VOL-LC,0),N2,1)/SMA(ABS(VOL-LC),N2,1)*100;\n\
+RSI3:SMA(MAX(VOL-LC,0),N3,1)/SMA(ABS(VOL-LC),N3,1)*100;'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.HSCOL = function ()
+{
+ let data =
+ {
+ Name: 'HSCOL', Description: '换手柱', IsMainIndex: false,
+ Args: [{ Name: 'N', Value: 5 }],
+ Script: //脚本
+ 'HSCOL:IF((SETCODE==0||SETCODE==1),100*VOL,VOL)/(FINANCE(7)/100),VOLSTICK;\n\
+MAHSL:MA(HSCOL,N);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.DBQRV = function ()
+{
+ let data =
+ {
+ Name: 'DBQRV', Description: '对比强弱量(需下载日线)', IsMainIndex: false,
+ Args: [{ Name: 'N', Value: 5 }],
+ Script: //脚本
+ 'ZS:(INDEXV-REF(INDEXV,N))/REF(INDEXV,N);\n\
+GG:(VOL-REF(VOL,N))/REF(VOL,N);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.DBLB = function ()
+{
+ let data =
+ {
+ Name: 'DBLB', Description: '对比量比(需下载日线)', IsMainIndex: false,
+ Args: [{ Name: 'N', Value: 5 }, { Name: 'M', Value: 5 }],
+ Script: //脚本
+ 'GG:=VOL/SUM(REF(VOL,1),N);\n\
+ZS:=INDEXV/SUM(REF(INDEXV,1),N);\n\
+DBLB:GG/ZS;\n\
+MADBLB:MA(DBLB,M);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.ACD = function ()
+{
+ let data =
+ {
+ Name: 'ACD', Description: '升降线', IsMainIndex: false,
+ Args: [{ Name: 'M', Value: 20 }],
+ Script: //脚本
+ 'LC:=REF(CLOSE,1);\n\
+DIF:=CLOSE-IF(CLOSE>LC,MIN(LOW,LC),MAX(HIGH,LC));\n\
+ACD:SUM(IF(CLOSE==LC,0,DIF),0);\n\
+MAACD:EXPMEMA(ACD,M);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.EXPMA = function ()
+ {
+ let data =
+ {
+ Name: 'EXPMA', Description: '指数平均线', IsMainIndex: true,
+ Args: [{ Name: 'M1', Value: 12 }, { Name: 'M2', Value: 50 }],
+ Script: //脚本
+ 'EXP1:EMA(CLOSE,M1);\n\
+EXP2:EMA(CLOSE,M2);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.EXPMA_S = function ()
+{
+ let data =
+ {
+ Name: 'EXPMA_S', Description: '指数平均线-副图', IsMainIndex: false,
+ Args: [{ Name: 'M1', Value: 12 }, { Name: 'M2', Value: 50 }],
+ Script: //脚本
+ 'EXP1:EMA(CLOSE,M1);\n\
+EXP2:EMA(CLOSE,M2);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.HMA = function ()
+{
+ let data =
+ {
+ Name: 'HMA', Description: '高价平均线', IsMainIndex: true,
+ Args: [{ Name: 'M1', Value: 6 }, { Name: 'M2', Value: 12 }, { Name: 'M3', Value: 30 }, { Name: 'M4', Value: 72 }, { Name: 'M5', Value: 144 }],
+ Script: //脚本
+ 'HMA1:MA(HIGH,M1);\n\
+HMA2:MA(HIGH,M2);\n\
+HMA3:MA(HIGH,M3);\n\
+HMA4:MA(HIGH,M4);\n\
+HMA5:MA(HIGH,M5);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.LMA = function ()
+{
+ let data =
+ {
+ Name: 'LMA', Description: '低价平均线', IsMainIndex: true,
+ Args: [{ Name: 'M1', Value: 6 }, { Name: 'M2', Value: 12 }, { Name: 'M3', Value: 30 }, { Name: 'M4', Value: 72 }, { Name: 'M5', Value: 144 }],
+ Script: //脚本
+ 'LMA1:MA(LOW,M1);\n\
+LMA2:MA(LOW,M2);\n\
+LMA3:MA(LOW,M3);\n\
+LMA4:MA(LOW,M4);\n\
+LMA5:MA(LOW,M5);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.VMA = function ()
+{
+ let data =
+ {
+ Name: 'VMA', Description: '变异平均线', IsMainIndex: true,
+ Args: [{ Name: 'M1', Value: 6 }, { Name: 'M2', Value: 12 }, { Name: 'M3', Value: 30 }, { Name: 'M4', Value: 72 }, { Name: 'M5', Value: 144 }],
+ Script: //脚本
+ 'VV:=(HIGH+OPEN+LOW+CLOSE)/4;\n\
+VMA1:MA(VV,M1);\n\
+VMA2:MA(VV,M2);\n\
+VMA3:MA(VV,M3);\n\
+VMA4:MA(VV,M4);\n\
+VMA5:MA(VV,M5);'
+
+ };
+
+ return data;
+}
+
+
+JSIndexScript.prototype.AMV = function ()
+{
+ let data =
+ {
+ Name: 'AMV', Description: '成本价均线', IsMainIndex: false,
+ Args: [{ Name: 'M1', Value: 6 }, { Name: 'M2', Value: 12 }, { Name: 'M3', Value: 30 }, { Name: 'M4', Value: 72 }, { Name: 'M5', Value: 144 }],
+ Script: //脚本
+ 'AMOV:=VOL*(OPEN+CLOSE)/2;\n\
+AMV1:SUM(AMOV,M1)/SUM(VOL,M1);\n\
+AMV2:SUM(AMOV,M2)/SUM(VOL,M2);\n\
+AMV3:SUM(AMOV,M3)/SUM(VOL,M3);\n\
+AMV4:SUM(AMOV,M4)/SUM(VOL,M4);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.BBIBOLL = function ()
+{
+ let data =
+ {
+ Name: 'BBIBOLL', Description: '多空布林线', IsMainIndex: true,
+ Args: [{ Name: 'N', Value: 11 }, { Name: 'M', Value: 6 }],
+ Script: //脚本
+ 'CV:=CLOSE;\n\
+BBIBOLL:(MA(CV,3)+MA(CV,6)+MA(CV,12)+MA(CV,24))/4;\n\
+UPR:BBIBOLL+M*STD(BBIBOLL,N);\n\
+DWN:BBIBOLL-M*STD(BBIBOLL,N);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.ALLIGAT = function ()
+{
+ let data =
+ {
+ Name: 'ALLIGAT', Description: '鳄鱼线', IsMainIndex: true,
+ Args: [],
+ Script: //脚本
+ 'NN:=(H+L)/2;\n\
+上唇:REF(MA(NN,5),3),COLOR40FF40;\n\
+牙齿:REF(MA(NN,8),5),COLOR0000C0;\n\
+下颚:REF(MA(NN,13),8),COLORFF4040;'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.ZX = function ()
+{
+ let data =
+ {
+ Name: 'ZX', Description: '重心线', IsMainIndex: false,
+ Args: [],
+ Script: //脚本
+ 'AV:0.01*AMOUNT/VOL;'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.XS = function ()
+{
+ let data =
+ {
+ Name: 'XS', Description: '薛斯通道', IsMainIndex: true,
+ Args: [{ Name: 'N', Value: 13 }],
+ Script: //脚本
+ 'VAR2:=CLOSE*VOL;\n\
+VAR3:=EMA((EMA(VAR2,3)/EMA(VOL,3)+EMA(VAR2,6)/EMA(VOL,6)+EMA(VAR2,12)/EMA(VOL,12)+EMA(VAR2,24)/EMA(VOL,24))/4,N);\n\
+SUP:1.06*VAR3;\n\
+SDN:VAR3*0.94;\n\
+VAR4:=EMA(CLOSE,9);\n\
+LUP:EMA(VAR4*1.14,5);\n\
+LDN:EMA(VAR4*0.86,5);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.XS2 = function ()
+{
+ let data =
+ {
+ Name: 'XS2', Description: '薛斯通道II', IsMainIndex: true,
+ Args: [{ Name: 'N', Value: 102 }, { Name: 'M', Value: 7 }],
+ Script: //脚本
+ 'AA:=MA((2*CLOSE+HIGH+LOW)/4,5); \n\
+通道1:AA*N/100; \n\
+通道2:AA*(200-N)/100; \n\
+CC:=ABS((2*CLOSE+HIGH+LOW)/4-MA(CLOSE,20))/MA(CLOSE,20); \n\
+DD:=DMA(CLOSE,CC); \n\
+通道3:(1+M/100)*DD; \n\
+通道4:(1-M/100)*DD;'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.SG_XDT = function ()
+{
+ let data =
+ {
+ Name: 'SG-XDT', Description: '心电图(需下载日线)', IsMainIndex: false,
+ Args: [{ Name: 'P1', Value: 5 }, { Name: 'P2', Value: 10 }],
+ Script: //脚本
+ 'QR:CLOSE/INDEXC*1000;\n\
+MQR1:MA(QR,5);\n\
+MQR2:MA(QR,10);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.SG_SMX = function ()
+{
+ let data =
+ {
+ Name: 'SG-SMX', Description: '生命线(需下载日线)', IsMainIndex: false,
+ Args: [{ Name: 'N', Value: 50 }],
+ Script: //脚本
+ 'H1:=HHV(HIGH,N);\n\
+L1:=LLV(LOW,N);\n\
+H2:=HHV(INDEXH,N);\n\
+L2:=LLV(INDEXL,N);\n\
+ZY:=CLOSE/INDEXC*2000;\n\
+ZY1:EMA(ZY,3);\n\
+ZY2:EMA(ZY,17);\n\
+ZY3:EMA(ZY,34);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.SG_LB = function ()
+{
+ let data =
+ {
+ Name: 'SG-LB', Description: '量比(需下载日线)', IsMainIndex: false,
+ Args: [],
+ Script: //脚本
+ 'ZY2:=VOL/INDEXV*1000;\n\
+量比:ZY2;\n\
+MA5:MA(ZY2,5);\n\
+MA10:MA(ZY2,10);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.SG_PF = function ()
+{
+ let data =
+ {
+ Name: 'SG-PF', Description: '强势股评分(需下载日线)', IsMainIndex: false,
+ Args: [],
+ Script: //脚本
+ 'ZY1:=CLOSE/INDEXC*1000;\n\
+A1:=IF(ZY1>HHV(ZY1,3),10,0);\n\
+A2:=IF(ZY1>HHV(ZY1,5),15,0);\n\
+A3:=IF(ZY1>HHV(ZY1,10),20,0);\n\
+A4:=IF(ZY1>HHV(ZY1,2),10,0);\n\
+A5:=COUNT(ZY1>REF(ZY1,1) ,9)*5;\n\
+强势股评分:A1+A2+A3+A4+A5;'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.RAD = function ()
+{
+ let data =
+ {
+ Name: 'RAD', Description: '威力雷达(需下载日线)', IsMainIndex: false,
+ Args: [{ Name: 'D', Value: 3 }, { Name: 'S', Value: 30 }, { Name: 'M', Value: 30 }],
+ Script: //脚本
+ 'SM:=(OPEN+HIGH+CLOSE+LOW)/4;\n\
+SMID:=MA(SM,D);\n\
+IM:=(INDEXO+INDEXH+INDEXL+INDEXC)/4;\n\
+IMID:=MA(IM,D);\n\
+SI1:=(SMID-REF(SMID,1))/SMID;\n\
+II:=(IMID-REF(IMID,1))/IMID;\n\
+RADER1:SUM((SI1-II)*2,S)*1000;\n\
+RADERMA:SMA(RADER1,M,1);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.SHT = function ()
+{
+ let data =
+ {
+ Name: 'SHT', Description: '龙系短线', IsMainIndex: false,
+ Args: [{ Name: 'N', Value: 5 }],
+ Script: //脚本
+ 'VAR1:=MA((VOL-REF(VOL,1))/REF(VOL,1),5);\n\
+VAR2:=(CLOSE-MA(CLOSE,24))/MA(CLOSE,24)*100;\n\
+MY: VAR2*(1+VAR1);\n\
+SHT: MY, COLORSTICK;\n\
+SHTMA: MA(SHT,N);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.ZLJC = function ()
+{
+ let data =
+ {
+ Name: 'ZLJC', Description: '主力进出', IsMainIndex: false,
+ Args: [],
+ Script: //脚本
+ 'VAR1:=(CLOSE+LOW+HIGH)/3; \n\
+VAR2:=SUM(((VAR1-REF(LOW,1))-(HIGH-VAR1))*VOL/100000/(HIGH-LOW),0); \n\
+VAR3:=EMA(VAR2,1); \n\
+JCS:VAR3; \n\
+JCM:MA(VAR3,12); \n\
+JCL:MA(VAR3,26);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.ZLMM = function ()
+{
+ let data =
+ {
+ Name: 'ZLMM', Description: '主力买卖', IsMainIndex: false,
+ Args: [],
+ Script: //脚本
+ 'LC :=REF(CLOSE,1);\n\
+RSI2:=SMA(MAX(CLOSE-LC,0),12,1)/SMA(ABS(CLOSE-LC),12,1)*100;\n\
+RSI3:=SMA(MAX(CLOSE-LC,0),18,1)/SMA(ABS(CLOSE-LC),18,1)*100;\n\
+MMS:MA(3*RSI2-2*SMA(MAX(CLOSE-LC,0),16,1)/SMA(ABS(CLOSE-LC),16,1)*100,3);\n\
+MMM:EMA(MMS,8);\n\
+MML:MA(3*RSI3-2*SMA(MAX(CLOSE-LC,0),12,1)/SMA(ABS(CLOSE-LC),12,1)*100,5);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.SLZT = function ()
+{
+ let data =
+ {
+ Name: 'SLZT', Description: '神龙在天', IsMainIndex: false,
+ Args: [],
+ Script: //脚本
+ '白龙: MA(CLOSE,125);\n\
+黄龙: 白龙+2*STD(CLOSE,170);\n\
+紫龙: 白龙-2*STD(CLOSE,145);\n\
+青龙: SAR(125,1,7), LINESTICK;\n\
+VAR2:=HHV(HIGH,70);\n\
+VAR3:=HHV(HIGH,20);\n\
+红龙: VAR2*0.83;\n\
+蓝龙: VAR3*0.91;'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.ADVOL = function ()
+{
+ let data =
+ {
+ Name: 'ADVOL', Description: '龙系离散量', IsMainIndex: false,
+ Args: [],
+ Script: //脚本
+ 'A:=SUM(((CLOSE-LOW)-(HIGH-CLOSE))*VOL/10000/(HIGH-LOW),0);\n\
+ADVOL:A;\n\
+MA1:MA(A,30);\n\
+MA2:MA(MA1,100);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.CYC = function ()
+{
+ let data =
+ {
+ Name: 'CYC', Description: '成本均线', IsMainIndex: true,
+ Args: [{ Name: 'P1', Value: 5 }, { Name: 'P2', Value: 13 }, { Name: 'P3', Value: 34 }],
+ Script: //脚本
+ 'JJJ:=IF(DYNAINFO(8)>0.01,0.01*DYNAINFO(10)/DYNAINFO(8),DYNAINFO(3));\n\
+DDD:=(DYNAINFO(5)<0.01 || DYNAINFO(6)<0.01);\n\
+JJJT:=IF(DDD,1,(JJJ<(DYNAINFO(5)+0.01) && JJJ>(DYNAINFO(6)-0.01)));\n\
+CYC1:IF(JJJT,0.01*EMA(AMOUNT,P1)/EMA(VOL,P1),EMA((HIGH+LOW+CLOSE)/3,P1));\n\
+CYC2:IF(JJJT,0.01*EMA(AMOUNT,P2)/EMA(VOL,P2),EMA((HIGH+LOW+CLOSE)/3,P2));\n\
+CYC3:IF(JJJT,0.01*EMA(AMOUNT,P3)/EMA(VOL,P3),EMA((HIGH+LOW+CLOSE)/3,P3));\n\
+CYC4:IF(JJJT,DMA(AMOUNT/(100*VOL),100*VOL/FINANCE(7)),EMA((HIGH+LOW+CLOSE)/3,120));'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.CYS = function ()
+{
+ let data =
+ {
+ Name: 'CYS', Description: '市场盈亏', IsMainIndex: false,
+ Args: [],
+ Script: //脚本
+ 'CYC13:EMA(AMOUNT,13)/EMA(VOL,13);\n\
+CYS:(CLOSE-CYC13)/CYC13*100;'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.CYQKL = function ()
+{
+ let data =
+ {
+ Name: 'CYQKL', Description: '博弈K线长度', IsMainIndex: false,
+ Args: [],
+ Script: //脚本
+ 'KL:100*(WINNER(CLOSE)-WINNER(OPEN));'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.SCR = function ()
+{
+ let data =
+ {
+ Name: 'SCR', Description: '筹码集中度', IsMainIndex: false,
+ Args: [{ Name: 'P1', Value: 90 }],
+ Script: //脚本
+ 'A:=P1+(100-P1)/2;\n\
+B:=(100-P1)/2;\n\
+CC:=COST(A);\n\
+DD:=COST(B);\n\
+SCR:(CC-DD)/(CC+DD)*100/2;'
+
+ };
+
+ return data;
+}
+
+
+JSIndexScript.prototype.ASR = function ()
+{
+ let data =
+ {
+ Name: 'ASR', Description: '浮筹比例', IsMainIndex: false,
+ Args: [],
+ Script: //脚本
+ 'ASR:(WINNER(C*1.1)-WINNER(C*0.9))/WINNER(HHV(H,0))*100;'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.SAR = function ()
+{
+ let data =
+ {
+ Name: 'SAR', Description: '抛物转向', IsMainIndex: true,
+ Args: [{ Name: 'P', Value: 10 },{ Name: 'STEP', Value: 2 },{ Name: 'MAXP', Value: 20 }],
+ Script: //脚本
+'S:SAR(P,STEP,MAXP),CIRCLEDOT;'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.TJCJL = function ()
+{
+ let data =
+ {
+ Name: '太极成交量', Description: '太极成交量', IsMainIndex: true,
+ Args: [],
+ Script: //脚本
+'总手:VOL,NODRAW;\n\
+ZZ:=IF(REF(C,1)>REF(O,1) AND O>REF(C,1)*1.014 AND CV5*1.2 AND V>V12*1.2 AND ZZ>2 AND C>H*0.975,0,VOL,10,0),COLORRED;\n\
+STICKLINE(CROSS(C6,C) AND V>V5*1.2 AND V>V12*1.2,0,VOL,10,0),COLORGREEN;\n\
+STICKLINE(VOL>MA(VOL,5)*2 AND V>V34*3 AND C][MA(VOL,5)*2 AND V>V34*3 AND C][V5*1.2 AND V>V12*1.2 AND ZZ>2 AND C>H*0.975,VOL*0.5,0,10,0),COLORRED;\n\
+STICKLINE(VOL>MA(VOL,5)*2 AND V>V34*3 AND C][V5*1.2 AND V>V12*1.2,VOL*0.5,0,10,0),COLORRED;'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.VOLRate = function ()
+{
+ let data =
+ {
+ Name: '量比', Description: '量比', IsMainIndex: false, Condition: { Period: [CONDITION_PERIOD.MINUTE_ID, CONDITION_PERIOD.MULTIDAY_MINUTE_ID] },
+ Args: [],
+ Script: //脚本
+ "LIANGBI:VOLR;"
+ };
+
+ return data;
+}
+
+/*
+ 飞龙四式-主图
+*/
+JSIndexScript.prototype.Dragon4_Main = function ()
+{
+ let data =
+ {
+ Name: '飞龙四式', Description: '飞龙四式', IsMainIndex: true,
+ Args: [{ Name: 'N1', Value: 5 }, { Name: 'N2', Value: 10 }, { Name: 'N3', Value: 50 }, { Name: 'N4', Value: 60 }],
+ Script: //脚本
+ '蜻蜓点水:=EMA(CLOSE,N1),COLORGRAY;\n\
+魔界:=EMA(CLOSE,N2),COLORGREEN;\n\
+水:=EMA(CLOSE,N3),COLORRED;\n\
+DRAWKLINE(HIGH,OPEN,LOW,CLOSE);\n\
+生命线:MA(CLOSE,N4),COLORBLUE,LINETHICK2;\n\
+DRAWBAND(魔界,\'RGB(186,225,250)\',水,\'RGB(253,194,124)\');\n\
+DRAWBAND(蜻蜓点水,\'RGB(128,138,135)\',魔界,\'RGB(0,0,255)\');'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.Dragon4_Fig = function () {
+ let data =
+ {
+ Name: '飞龙四式', Description: '飞龙四式', IsMainIndex: false,
+ Args: [],
+ Script: //脚本
+ '倍:VOL>=REF(V,1)*1.90 AND C>REF(C,1),COLORYELLOW;\n\
+低:VOL][REF(V,1),3)==3 AND COUNT(C>O,3)==3,COLORBROWN;\n\
+缩量涨:COUNT(C>REF(C,1),2)==2 AND COUNT(V][=REF(C,1),V,0,2,0),COLORRED;\n\
+STICKLINE(C][=2038 AND MONTH>=1,0,1);
+VAR2:=REF(LOW,1)*VAR1;
+VAR3:=SMA(ABS(LOW-VAR2),3,1)/SMA(MAX(LOW-VAR2,0),3,1)*100*VAR1;
+VAR4:=EMA(IF(CLOSE*1.3,VAR3*10,VAR3/10),3)*VAR1;
+VAR5:=LLV(LOW,30)*VAR1;
+VAR6:=HHV(VAR4,30)*VAR1;
+VAR7:=IF(MA(CLOSE,58),1,0)*VAR1;
+VAR8:=EMA(IF(LOW<=VAR5,(VAR4+VAR6*2)/2,0),3)/618*VAR7*VAR1;
+吸筹A:IF(VAR8>100,100,VAR8)*VAR1,COLORRED;
+吸筹B:STICKLINE(吸筹A>-150,0,吸筹A,8,0),COLORRED;
+
+散户线: 100*(HHV(HIGH,M)-CLOSE)/(HHV(HIGH,M)-LLV(LOW,M)),COLORFFFF00,LINETHICK2;
+RSV:=(CLOSE-LLV(LOW,N))/(HHV(HIGH,N)-LLV(LOW,N))*100;
+K:=SMA(RSV,3,1);
+D:=SMA(K,3,1);
+J:=3*K-2*D;
+主力线:EMA(J,5),COLORFF00FF,LINETHICK2;
+DRAWICON(CROSS(主力线,散户线),主力线,1);
+DRAWICON(CROSS(散户线,主力线),主力线,2);
+*/
+
+JSIndexScript.prototype.FundsAnalysis = function ()
+{
+ let data =
+ {
+ Name: '资金分析', Description: '资金分析', IsMainIndex: false,
+ Args: [{ Name: 'M', Value: 55 }, { Name: 'N', Value: 34 }],
+ Script: //脚本
+ 'LC:=REF(CLOSE,1);\n\
+RSI:=((SMA(MAX((CLOSE - LC),0),3,1) / SMA(ABS((CLOSE - LC)),3,1)) * 100);\n\
+FF:=EMA(CLOSE,3);\n\
+MA15:=EMA(CLOSE,21); DRAWTEXT(CROSS(85,RSI),75,\'▼\'),COLORGREEN;\n\
+VAR1:=IF(YEAR>=2038 AND MONTH>=1,0,1);\n\
+VAR2:=REF(LOW,1)*VAR1;\n\
+VAR3:=SMA(ABS(LOW-VAR2),3,1)/SMA(MAX(LOW-VAR2,0),3,1)*100*VAR1;\n\
+VAR4:=EMA(IF(CLOSE*1.3,VAR3*10,VAR3/10),3)*VAR1;\n\
+VAR5:=LLV(LOW,30)*VAR1;\n\
+VAR6:=HHV(VAR4,30)*VAR1;\n\
+VAR7:=IF(MA(CLOSE,58),1,0)*VAR1;\n\
+VAR8:=EMA(IF(LOW<=VAR5,(VAR4+VAR6*2)/2,0),3)/618*VAR7*VAR1;\n\
+吸筹A:IF(VAR8>100,100,VAR8)*VAR1,COLORFB2F3B;\n\
+{吸筹B}STICKLINE(吸筹A>-150,0,吸筹A,8,0),COLORFB2F3B;\n\
+\n\
+散户线: 100*(HHV(HIGH,M)-CLOSE)/(HHV(HIGH,M)-LLV(LOW,M)),COLORAA89BD,LINETHICK2;\n\
+RSV:=(CLOSE-LLV(LOW,N))/(HHV(HIGH,N)-LLV(LOW,N))*100;\n\
+K:=SMA(RSV,3,1);\n\
+D:=SMA(K,3,1);\n\
+J:=3*K-2*D;\n\
+主力线:EMA(J,5),COLORF39800,LINETHICK2;\n\
+DRAWICON(CROSS(主力线,散户线),主力线,1);\n\
+DRAWICON(CROSS(散户线,主力线),主力线,2);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.MarginProportion = function ()
+{
+ let data =
+ {
+ Name: '融资占比(%)', Description: '融资占比', IsMainIndex: false,
+ Args: [],
+ Script: //脚本
+ '占比:MARGIN(2);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.BTX = function ()
+{
+ let data =
+ {
+ Name: 'BTX', Description: '宝塔线', IsMainIndex: false,
+ Args: [],
+ Script: //脚本
+ 'B1:=REF(C,1);\n\
+B2:= REF(C, 2);\n\
+SS:= IF(C > REF(C, 1) AND REF(C, 1) >= REF(C, 2), 1, IF(C < REF(C, 1) AND REF(C, 1) <= REF(C, 2), -1, IF(C > REF(C, 2) AND REF(C, 2) > REF(C, 1), 2, IF(C < REF(C, 2) AND REF(C, 2) < REF(C, 1), -2, 0))));\n\
+SM:= IF(REF(SS, 1) <> 0, REF(SS, 1), IF(REF(SS, 2) <> 0, REF(SS, 2), IF(REF(SS, 3) <> 0, REF(SS, 3), IF(REF(SS, 5) <> 0, REF(SS, 5), IF(REF(SS, 6) <> 0, REF(SS, 6), IF(REF(SS, 7) <> 0, REF(SS, 7), 0))))));\n\
+MC:= IF(REF(SS, 1) <> 0, B2, IF(SM > 0, MIN(B1, B2), MAX(B1, B2)));\n\
+TOW1:= IF(C > REF(C, 1), C, REF(C, 1));\n\
+TOW2:= IF((SS == -1 OR SS == -2) AND SM > 0, B2, TOW1);\n\
+TOWER:= IF(TOW1 > TOW2, TOW1, TOW2);\n\
+STICKLINE(SS == 1 OR SM >= 1 AND SS == 0, B1, C, 10, 1), COLORRED;\n\
+STICKLINE(SS == -1 OR SM <= -1 AND SS == 0, B1, C, 10, 0), COLORCYAN;\n\
+STICKLINE(SS == 2, B2, C, 10, 1), COLORRED;\n\
+STICKLINE(SS == -2, B2, C, 10, 0), COLORCYAN;\n\
+STICKLINE((SS == -1 OR SS == -2) AND SM > 0, B2, B1, 10, 1), COLORRED;\n\
+STICKLINE((SS == 1 OR SS == 2) AND SM < 0, B2, B1, 10, 0), COLORCYAN;'
+ };
+
+ return data;
+}
+
+
+JSIndexScript.prototype.EMPTY = function ()
+{
+ let data =
+ {
+ Name: '', Description: '空指标', IsMainIndex: true,
+ Args: [],
+ Script: //脚本
+ 'VAR2:=C;'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.FXG_BSPoint = function ()
+{
+ let data =
+ {
+ Name: '操盘BS点', Description: '操盘BS点', IsMainIndex: true,
+ Args: [],
+ Script: //脚本
+ 'MA5:MA(CLOSE,5);\n\
+ MA13:MA(CLOSE,13);\n\
+ MA21:MA(CLOSE,21);\n\
+ MA34:MA(CLOSE,34);\n\
+ {MA55:MA(CLOSE,55),COLOR0000FF;}\n\
+ {MA120:=MA(CLOSE,120),COLORFFFF00;}\n\
+ 天使:=EMA(C,2),COLOR000000;\n\
+ 魔鬼:=EMA(SLOPE(C,21)*20+C,42),COLOR000000;\n\
+ 买:=CROSS(天使,魔鬼);\n\
+ 卖:=CROSS(魔鬼,天使);\n\
+ DRAWICON(买,L*0.99,13),COLORYELLOW;\n\
+ DRAWICON(卖,H*1.01,14),COLORGREEN;\n\
+ DRAWKLINE_IF(天使>=魔鬼,HIGH,CLOSE,LOW,OPEN),COLORRED;\n\
+ DRAWKLINE_IF(天使<魔鬼,HIGH,CLOSE,LOW,OPEN),COLORBLUE;\n\
+ DRAWKLINE_IF(CROSS(天使,魔鬼),HIGH,CLOSE,LOW,OPEN),COLORYELLOW;\n\
+ DRAWKLINE_IF(CROSS(魔鬼,天使),HIGH,CLOSE,LOW,OPEN),COLORBLACK;'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.NewsNegative=function()
+{
+ let data=
+ {
+ Name: '负面新闻', Description: '负面新闻统计', IsMainIndex: false,
+ Args: [{ Name: 'N', Value: 5 }, { Name: 'N2', Value: 10 }],
+ Script: //脚本
+ '负面:NEWS(1);\n\
+ MA1:MA(负面,N);\n\
+ MA2:MA(负面,N2);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.NewsResearch = function () {
+ let data =
+ {
+ Name: '机构调研', Description: '机构调研统计', IsMainIndex: false,
+ Args: [{ Name: 'N', Value: 5 }, { Name: 'N2', Value: 10 }],
+ Script: //脚本
+ '次数:NEWS(2);\n\
+ MA1:MA(次数,N);\n\
+ MA2:MA(次数,N2);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.NewsInteract = function () {
+ let data =
+ {
+ Name: '董秘连线', Description: '互动易统计', IsMainIndex: false,
+ Args: [{ Name: 'N', Value: 5 }, { Name: 'N2', Value: 10 }],
+ Script: //脚本
+ '个数:NEWS(3);\n\
+ MA1:MA(个数,N);\n\
+ MA2:MA(个数,N2);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.UpDownAnalyze = function ()
+{
+ let data =
+ {
+ Name: '涨跌趋势', Description: '涨跌趋势', IsMainIndex: false, FloatPrecision: 0,
+ Args: [],
+ Script: //脚本
+ "上涨家数:UPCOUNT('CNA.CI'),COLORRED;\n\
+下跌家数:DOWNCOUNT('CNA.CI'),COLORGREEN;"
+ };
+
+ return data;
+}
+
+//外包指标
+JSIndexScript.prototype.FXG_BSPoint = function ()
+{
+ let data =
+ {
+ Name: '操盘BS点', Description: '操盘BS点', IsMainIndex: true,
+ Args: [],
+ Script: //脚本
+ 'MA5:MA(CLOSE,5);\n\
+ MA13:MA(CLOSE,13);\n\
+ MA21:MA(CLOSE,21);\n\
+ MA34:MA(CLOSE,34);\n\
+ {MA55:MA(CLOSE,55),COLOR0000FF;}\n\
+ {MA120:=MA(CLOSE,120),COLORFFFF00;}\n\
+ 天使:=EMA(C,2),COLOR000000;\n\
+ 魔鬼:=EMA(SLOPE(C,21)*20+C,42),COLOR000000;\n\
+ 买:=CROSS(天使,魔鬼);\n\
+ 卖:=CROSS(魔鬼,天使);\n\
+ SUPERDRAWTEXT(买,L,"B",2,5),COLORYELLOW;\n\
+ SUPERDRAWTEXT(卖,L,"S",1,5),COLORGREEN;\n\
+ DRAWKLINE_IF(天使>=魔鬼,HIGH,CLOSE,LOW,OPEN),COLORRED;\n\
+ DRAWKLINE_IF(天使<魔鬼,HIGH,CLOSE,LOW,OPEN),COLORBLUE;\n\
+ DRAWKLINE_IF(CROSS(天使,魔鬼),HIGH,CLOSE,LOW,OPEN),COLORYELLOW;\n\
+ DRAWKLINE_IF(CROSS(魔鬼,天使),HIGH,CLOSE,LOW,OPEN),COLORBLACK;'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.FXG_INDEX = function ()
+{
+ let data =
+ {
+ Name: '涨停多空线', Description: '涨停多空线', IsMainIndex: false,
+ Args: [],
+ Script: //脚本
+ '做多能量线: SMA((CLOSE-LLV(LOW,9))/(HHV(HIGH,9)-LLV(LOW,9))*100,5,1)-8,COLORRED,LINETHICK3;\n\
+做空能量线: SMA((HHV(HIGH,36)-CLOSE)/(HHV(HIGH,36)-LLV(LOW,36))*100,2,1),COLORGREEN,LINETHICK3;\n\
+20,POINTDOT,COLORF00FF0;\n\
+50,POINTDOT,COLORGREEN;\n\
+80,POINTDOT,COLORLIBLUE;'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.FXG_INDEX2 = function ()
+{
+ let data =
+ {
+ Name: '涨停吸筹区', Description: '涨停吸筹区', IsMainIndex: false,
+ Args: [],
+ Script: //脚本
+ 'VAR0:=EMA(HHV(HIGH,500),21); \n\
+VAR1:=EMA(HHV(HIGH,250),21);\n\
+VAR2:=EMA(HHV(HIGH,90),21); \n\
+VAR3:=EMA(LLV(LOW,500),21); \n\
+VAR4:=EMA(LLV(LOW,250),21); \n\
+VAR5:=EMA(LLV(LOW,90),21);\n\
+\n\
+VAR6:=EMA((VAR3*0.96+VAR4*0.96+VAR5*0.96+VAR0*0.558+VAR1*0.558+VAR2*0.558)/6,21); \n\
+VAR7:=EMA((VAR3*1.25+VAR4*1.23+VAR5*1.2+VAR0*0.55+VAR1*0.55+VAR2*0.65)/6,21); \n\
+VAR8:=EMA((VAR3*1.3+VAR4*1.3+VAR5*1.3+VAR0*0.68+VAR1*0.68+VAR2*0.68)/6,21); \n\
+VAR9:=EMA((VAR6*3+VAR7*2+VAR8)/6*1.738,21); \n\
+VAR10:=REF(LOW,1); \n\
+VAR11:=SMA(ABS(LOW-VAR10),3,1)/SMA(MAX(LOW-VAR10,0),3,1)*100; \n\
+VAR12:=EMA(IFF(CLOSE*1.35<=VAR9,VAR11*10,VAR11/10),3); \n\
+VAR13:=LLV(LOW,30); \n\
+VAR14:=HHV(VAR12,30); \n\
+VAR15:=IFF(MA(CLOSE,58),1,0); \n\
+VAR16:=EMA(IFF(LOW<=VAR13,(VAR12+VAR14*2)/2,0),3)/618*VAR15;\n\
+\n\
+资金入场:IFF(VAR16>0,VAR16,0),LINETHICK,LINETHICK2, COLORFF0000; \n\
+\n\
+A1:IFF(资金入场>0,资金入场*1.2,0),STICK,LINETHICK5, COLORFF0000;\n\
+A2:IFF(资金入场>0,资金入场*0.8,0),STICK,LINETHICK5, COLORFF6600;\n\
+A3:IFF(资金入场>0,资金入场*0.6,0),STICK,LINETHICK5, COLORFF9900;\n\
+A4:IFF(资金入场>0,资金入场*0.4,0) ,STICK,LINETHICK5,COLORFFCC00;\n\
+A5:IFF(资金入场>0,资金入场*0.2,0) ,STICK,LINETHICK5,COLORFFFF00;'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.FXG_INDEX3 = function ()
+{
+ let data =
+ {
+ Name: '量能黄金点', Description: '量能黄金点', IsMainIndex: false,
+ Args: [],
+ Script: //脚本
+ 'A:=IFF((CLOSE>126.32),VOL,VOL); \n\
+主力:=MA(A,4),COLORRED;\n\
+游资:=MA(A,8),COLORYELLOW;\n\
+大户:=MA(A,16),COLORF0F000;\n\
+散户:=MA(A,32),COLOR00FF00;\n\
+主比:=ABS(((主力)/(主力 + 游资 + 大户 + 散户))*(100)),LINESTICK,COLORRED;\n\
+游比:=ABS(((游资)/(主力 + 游资 + 大户 + 散户))*(100)),LINESTICK,COLORYELLOW;\n\
+大比:=ABS(((大户)/(主力 + 游资 + 大户 + 散户))*(100)),LINESTICK,COLORF0F000;\n\
+散比:=ABS(((散户)/(主力 + 游资 + 大户 + 散户))*(100)),LINESTICK,COLOR00FF00;\n\
+警戒线:MA(A,180),COLORFF66FF;\n\
+STICKLINE((主力 > 0),0,主力,2.5,0),COLOR1020BB;\n\
+STICKLINE((主力 > 0),0,主力,0.7,0),COLORRED;\n\
+STICKLINE((游资 > 0),0,游资,2.5,0),COLOR009CFF;\n\
+STICKLINE((游资 > 0),0,游资,0.7,0),COLORYELLOW;\n\
+STICKLINE((大户 > 0),0,大户,2.5,0),COLORFF8800;\n\
+STICKLINE((大户 > 0),0,大户,0.7,0),COLORLIBLUE;\n\
+STICKLINE((散户 > 0),0,散户,2.5,0),COLOR00CA00;\n\
+STICKLINE((散户 > 0),0,散户,0.7,0),COLORGREEN;'
+ };
+
+ return data;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+//五彩K线
+
+JSIndexScript.prototype.COLOR_KSTAR1 = function ()
+{
+ let data =
+ {
+ Name: '十字星', Description: '十字星', IsMainIndex: true, InstructionType: 2,
+ Script: //脚本
+ 'KSTAR:CLOSE==OPEN&&HIGH>LOW;'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_KSTAR2 = function ()
+{
+ let data =
+ {
+ Name: '早晨之星', Description: '早晨之星', IsMainIndex: true, InstructionType: 2,
+ Script: //脚本
+ 'KSTAR:(REF(CLOSE,2)/REF(OPEN,2)<0.95) && (REF(OPEN,1) < REF(CLOSE,2)) && (ABS(REF(OPEN,1)-REF(CLOSE,1))/REF(CLOSE,1)<0.03) && CLOSE/OPEN>1.05 && CLOSE>REF(CLOSE,2);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_KSTAR3 = function ()
+{
+ let data =
+ {
+ Name: '黄昏之星', Description: '黄昏之星', IsMainIndex: true, InstructionType: 2,
+ Script: //脚本
+ 'KSTAR:REF(CLOSE,2)/REF(OPEN,2)>1.05 && REF(OPEN,1)>REF(CLOSE,2) && ABS(REF(OPEN,1)-REF(CLOSE,1))/REF(CLOSE,1)<0.03 && CLOSE/OPEN<0.95 && CLOSE][1.03;'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_K220 = function ()
+{
+ let data =
+ {
+ Name: '身怀六甲', Description: '身怀六甲', IsMainIndex: true, InstructionType: 2,
+ Script: //脚本
+ 'KSTAR:ABS(REF(CLOSE,1)-REF(OPEN,1))/REF(CLOSE,1)>0.04&&\n\
+ ABS(CLOSE-OPEN)/CLOSE<0.005&&\n\
+ MAX(CLOSE,OPEN)MIN(REF(CLOSE,1),REF(OPEN,1));'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_K300 = function ()
+{
+ let data =
+ {
+ Name: '三个白武士', Description: '三个白武士', IsMainIndex: true, InstructionType: 2,
+ Script: //脚本
+ 'KSTAR:UPNDAY(CLOSE,3)&&NDAY(CLOSE,OPEN,3);'
+ };
+
+ return data;
+}
+
+
+JSIndexScript.prototype.COLOR_K310 = function ()
+{
+ let data =
+ {
+ Name: '三只乌鸦', Description: '三只乌鸦', IsMainIndex: true, InstructionType: 2,
+ Script: //脚本
+ 'KSTAR:DOWNNDAY(CLOSE,3)&&NDAY(OPEN,CLOSE,3);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_K380 = function ()
+{
+ let data =
+ {
+ Name: '光头阳线', Description: '光头阳线', IsMainIndex: true, InstructionType: 2,
+ Script: //脚本
+ 'KSTAR:HIGH==CLOSE&&HIGH>LOW;'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_K390 = function ()
+{
+ let data =
+ {
+ Name: '光脚阴线', Description: '光脚阴线', IsMainIndex: true, InstructionType: 2,
+ Script: //脚本
+ 'KSTAR:LOW==CLOSE&&HIGH>LOW;'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_K134 = function ()
+{
+ let data =
+ {
+ Name: '垂死十字', Description: '垂死十字', IsMainIndex: true, InstructionType: 2,
+ Script: //脚本
+ 'KSTAR:CLOSE==OPEN&&CLOSE==LOW&&CLOSE1.05&&CLOSE>REF(CLOSE,2);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_K150 = function ()
+{
+ let data =
+ {
+ Name: '黄昏十字星', Description: '黄昏十字星', IsMainIndex: true, InstructionType: 2,
+ Script: //脚本
+ 'KSTAR:REF(CLOSE,2)/REF(OPEN,2)>1.05&&\n\
+REF(OPEN,1)>REF(CLOSE,2)&&\n\
+REF(OPEN,1)=REF(CLOSE,1)&&\n\
+CLOSE/OPEN<0.95&&CLOSE][3*(MAX(OPEN,CLOSE)-LOW)&&\n\
+CLOSE>MA(CLOSE,5);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_K165 = function ()
+{
+ let data =
+ {
+ Name: '倒转锤头', Description: '倒转锤头', IsMainIndex: true, InstructionType: 2,
+ Script: //脚本
+ 'KSTAR:MIN(OPEN,CLOSE)==LOW&&\n\
+HIGH-LOW>3*(MAX(OPEN,CLOSE)-LOW)&&\n\
+CLOSE3*(HIGH-MIN(OPEN,CLOSE))&&\n\
+CLOSE3*(HIGH-MIN(OPEN,CLOSE))&&\n\
+CLOSE>MA(CLOSE,5);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_K190 = function ()
+{
+ let data =
+ {
+ Name: '穿头破脚', Description: '穿头破脚', IsMainIndex: true, InstructionType: 2,
+ Script: //脚本
+ 'OUT:(REF(CLOSE,1)/REF(OPEN,1)>1.03&&\n\
+CLOSE/OPEN<0.96&&\n\
+CLOSE][REF(CLOSE,1))||\n\
+(REF(CLOSE,1)/REF(OPEN,1)<0.97&&\n\
+CLOSE/OPEN>1.04&&\n\
+CLOSE>REF(OPEN,1)&&OPEN][REF(VOL,1)||VOL>(CAPITAL*0.1);\n\
+BB:=OPEN>=(REF(HIGH,1))&&REF(HIGH,1)>(REF(HIGH,2)*1.06);\n\
+CC:=CLOSE>(REF(CLOSE,1))-(REF(CLOSE,1)*0.01);\n\
+DD:=CLOSE<(HIGH*0.965) && HIGH>(OPEN*1.05);\n\
+EE:=LOW(REF(CLOSE,1)*1.06);\n\
+FF:=(HIGH-(MAX(OPEN,CLOSE)))/2>(MIN(OPEN,CLOSE))-LOW;\n\
+GG:=(ABS(OPEN-CLOSE))/2<(MIN(OPEN,CLOSE)-LOW);\n\
+SWORDO:AA&&BB&&CC&&DD&&EE&&FF&&GG;'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_CSFR = function ()
+{
+ let data =
+ {
+ Name: '出水芙蓉', Description: '出水芙蓉', IsMainIndex: true, InstructionType: 2,
+ Script: //脚本
+ 'A:=CLOSE>OPEN;\n\
+B:=A&&CLOSE>MA(CLOSE,S)&&CLOSE>MA(CLOSE,M)&&CLOSE>MA(CLOSE,LL);\n\
+CC:=B&&OPEN0.0618*CLOSE;'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_WYGD = function ()
+{
+ let data =
+ {
+ Name: '乌云盖顶', Description: '乌云盖顶', IsMainIndex: true, InstructionType: 2,
+ Script: //脚本
+ 'VAR1:BACKSET( \n\
+REF(CLOSE,1)/REF(OPEN,1)>1.03 AND \n\
+CLOSE/OPEN<0.97 AND \n\
+OPEN>REF(CLOSE,1) AND CLOSE][1.03 AND \n\
+OPEN][REF(CLOSE,1), 3);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_SZTAI = function ()
+{
+ let data =
+ {
+ Name: '十字胎', Description: '十字胎', IsMainIndex: true, InstructionType: 2,
+ Script: //脚本
+ 'VAR1:BACKSET( ABS(REF(CLOSE,1)-REF(OPEN,1))/REF(CLOSE,1) > 0.04 AND \n\
+CLOSE==OPEN AND CLOSE < MAX(REF(CLOSE,1),REF(OPEN,1)) AND \n\
+CLOSE > MIN(REF(CLOSE,1),REF(OPEN,1)), 2);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_PINGDING = function ()
+{
+ let data =
+ {
+ Name: '平顶', Description: '平顶', IsMainIndex: true, InstructionType: 2,
+ Script: //脚本
+ 'VAR1:BACKSET(ABS(HIGH-REF(HIGH,1))/HIGH<0.001,2);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_PINGDI = function ()
+{
+ let data =
+ {
+ Name: '平底', Description: '平底', IsMainIndex: true, InstructionType: 2,
+ Script: //脚本
+ 'VAR1:BACKSET((ABS(LOW-REF(LOW,1))/LOW<0.001 AND \n\
+ABS(REF(LOW,1)-REF(LOW,2))/REF(LOW,1)<=0.001),2);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_DAYANZHU = function ()
+{
+ let data =
+ {
+ Name: '大阳烛', Description: '大阳烛', IsMainIndex: true, InstructionType: 2,
+ Script: //脚本
+ 'VAR1:CLOSE/OPEN>1.05 AND HIGH/LOW < CLOSE/OPEN+0.018;'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_DAYINGZHU = function ()
+{
+ let data =
+ {
+ Name: '大阴烛', Description: '大阴烛', IsMainIndex: true, InstructionType: 2,
+ Script: //脚本
+ 'VAR1:OPEN/CLOSE > 1.05 AND HIGH/LOW < OPEN/CLOSE+0.018;'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_HYFG = function ()
+{
+ let data =
+ {
+ Name: '好友反攻', Description: '好友反攻', IsMainIndex: true, InstructionType: 2,
+ Script: //脚本
+ 'VAR1:BACKSET( (REF(CLOSE,1)][OPEN AND ABS(CLOSE-REF(CLOSE,1))/CLOSE<0.002),2);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_TKQK = function ()
+{
+ let data =
+ {
+ Name: '跳空缺口', Description: '跳空缺口', IsMainIndex: true, InstructionType: 2,
+ Script: //脚本
+ 'VAR1:BACKSET( HIGH][REF(HIGH,1),2);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_SFWY = function ()
+{
+ let data =
+ {
+ Name: '双飞乌鸦', Description: '双飞乌鸦', IsMainIndex: true, InstructionType: 2,
+ Script: //脚本
+ 'VAR1:BACKSET( REF(CLOSE,1)][1.03 AND \n\
+REF(CLOSE,3)][REF(HIGH,3) AND \n\
+REF(HIGH,4)>REF(HIGH,2) AND \n\
+REF(HIGH,4)>REF(HIGH,1) AND \n\
+CLOSE/OPEN>1.03 AND \n\
+CLOSE>REF(CLOSE,4), 5);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_XDSBQ = function ()
+{
+ let data =
+ {
+ Name: '下跌三部曲', Description: '下跌三部曲', IsMainIndex: true, InstructionType: 2,
+ Script: //脚本
+ 'VAR1:BACKSET( \n\
+REF(CLOSE,4)/REF(OPEN,4)<0.97 AND \n\
+REF(CLOSE,3)>REF(OPEN,3) AND \n\
+REF(CLOSE,2)>REF(OPEN,2) AND \n\
+REF(CLOSE,1)>REF(OPEN,1) AND \n\
+REF(LOW,4)][REF(HIGH,3) AND \n\
+REF(HIGH,4)>REF(HIGH,2) AND \n\
+REF(HIGH,4)>REF(HIGH,1) AND \n\
+CLOSE/OPEN<0.97 AND \n\
+CLOSE][0.667;'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_CHSY = function ()
+{
+ let data =
+ {
+ Name: '长上影', Description: '长上影', IsMainIndex: true, InstructionType: 2,
+ Script: //脚本
+ 'VAR2:(HIGH-MAX(CLOSE,OPEN))/(HIGH-LOW)>0.667,COLORBLUE;'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_FENLI = function ()
+{
+ let data =
+ {
+ Name: '分离', Description: '分离', IsMainIndex: true, InstructionType: 2,
+ Script: //脚本
+ 'VAR1:BACKSET( OPEN==REF(OPEN,1) AND (CLOSE-OPEN)*(REF(CLOSE,1)-REF(OPEN,1))<0,2);'
+ };
+
+ return data;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//交易系统
+
+JSIndexScript.prototype.TRADE_BIAS = function ()
+{
+ let data =
+ {
+ Name: 'BIAS', Description: '乖离率专家系统', IsMainIndex: true, InstructionType: 1,
+ Args: [{ Name: 'N', Value: 12 }, { Name: 'LL', Value: 6 }, { Name: 'LH', Value: 6 }],
+ Script: //脚本
+ 'BIAS:=(CLOSE-MA(CLOSE,N))/MA(CLOSE,N)*100;\n\
+ENTERLONG:CROSS(-LL,BIAS);\n\
+EXITLONG:CROSS(BIAS,LH);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.TRADE_CCI = function ()
+{
+ let data =
+ {
+ Name: 'CCI', Description: 'CCI专家系统', IsMainIndex: true, InstructionType: 1,
+ Args: [{ Name: 'N', Value: 14 }],
+ Script: //脚本
+ 'TYP:=(HIGH+LOW+CLOSE)/3;\n\
+CCI:=(TYP-MA(TYP,N))/(0.015*AVEDEV(TYP,N));\n\
+INDEX:=CCI;\n\
+ENTERLONG:CROSS(INDEX,-100);\n\
+EXITLONG:CROSS(100,INDEX);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.TRADE_DMI = function ()
+{
+ let data =
+ {
+ Name: 'DMI', Description: '趋向专家系统', IsMainIndex: true, InstructionType: 1,
+ Args: [{ Name: 'N', Value: 14 }],
+ Script: //脚本
+ 'MTR:=SUM(MAX(MAX(HIGH-LOW,ABS(HIGH-REF(CLOSE,1))),ABS(LOW-REF(CLOSE,1))),N);\n\
+HD :=HIGH-REF(HIGH,1);\n\
+LD :=REF(LOW,1)-LOW;\n\
+PDM:=SUM(IF(HD>0&&HD>LD,HD,0),N);\n\
+MDM:=SUM(IF(LD>0&&LD>HD,LD,0),N);\n\
+PDI:=PDM*100/MTR;\n\
+MDI:=MDM*100/MTR;\n\
+ENTERLONG:CROSS(PDI,MDI);\n\
+EXITLONG:CROSS(MDI,PDI);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.TRADE_KD = function ()
+{
+ let data =
+ {
+ Name: 'KD', Description: 'KD指标专家系统', IsMainIndex: true, InstructionType: 1,
+ Args: [{ Name: 'N', Value: 9 }, { Name: 'M1', Value: 3 }, { Name: 'M2', Value: 3 }],
+ Script: //脚本
+ 'WRSV:=(CLOSE-LLV(LOW,N))/(HHV(HIGH,N)-LLV(LOW,N))*100;\n\
+WK:=SMA(WRSV,M1,1);\n\
+D:=SMA(WK,M2,1);\n\
+ENTERLONG:CROSS(WK,D)&&WK<20;\n\
+EXITLONG:CROSS(D,WK)&&WK>80;'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.TRADE_BOLL = function ()
+{
+ let data =
+ {
+ Name: 'BOLL', Description: '布林带专家系统', IsMainIndex: true, InstructionType: 1,
+ Args: [{ Name: 'N', Value: 20 }],
+ Script: //脚本
+ 'MID :=MA(CLOSE,N);\n\
+UPPER:=MID+2*STD(CLOSE,N);\n\
+LOWER:=MID-2*STD(CLOSE,N);\n\
+ENTERLONG:CROSS(CLOSE,LOWER);\n\
+EXITLONG:CROSS(CLOSE,UPPER);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.TRADE_KDJ = function ()
+{
+ let data =
+ {
+ Name: 'KDJ', Description: 'KDJ专家系统', IsMainIndex: true, InstructionType: 1,
+ Args: [{ Name: 'N', Value: 9 }, { Name: 'M1', Value: 3 }],
+ Script: //脚本
+ 'RSV:=(CLOSE-LLV(LOW,N))/(HHV(HIGH,N)-LLV(LOW,N))*100;\n\
+K:=SMA(RSV,M1,1);\n\
+D:=SMA(K,M1,1);\n\
+J:=3*K-2*D;\n\
+ENTERLONG:CROSS(J,0);\n\
+EXITLONG:CROSS(100,J);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.TRADE_MA = function ()
+{
+ let data =
+ {
+ Name: 'MA', Description: '均线专家系统', IsMainIndex: true, InstructionType: 1,
+ Args: [{ Name: 'SHORT', Value: 5 }, { Name: 'LONG', Value: 20 }],
+ Script: //脚本
+ 'ENTERLONG:CROSS(MA(CLOSE,SHORT),MA(CLOSE,LONG));\n\
+EXITLONG:CROSS(MA(CLOSE,LONG),MA(CLOSE,SHORT));'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.TRADE_MACD = function ()
+{
+ let data =
+ {
+ Name: 'MACD', Description: 'MACD专家系统', IsMainIndex: true, InstructionType: 1,
+ Args: [{ Name: 'LONG', Value: 26 }, { Name: 'SHORT', Value: 12 }, { Name: 'M', Value: 9 }],
+ Script: //脚本
+ 'DIFF:=EMA(CLOSE,SHORT) - EMA(CLOSE,LONG);\n\
+DEA := EMA(DIFF,M);\n\
+MACD := 2*(DIFF-DEA);\n\
+ENTERLONG:CROSS(MACD,0);\n\
+EXITLONG:CROSS(0,MACD);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.TRADE_MTM = function ()
+{
+ let data =
+ {
+ Name: 'MTM', Description: '动力指标专家系统', IsMainIndex: true, InstructionType: 1,
+ Args: [{ Name: 'N', Value: 6 }],
+ Script: //脚本
+ 'WMTM:=C-REF(C,N);\n\
+ENTERLONG:CROSS(WMTM,0);\n\
+EXITLONG:CROSS(0,WMTM);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.TRADE_PSY = function ()
+{
+ let data =
+ {
+ Name: 'PSY', Description: 'PSY心理线专家系统', IsMainIndex: true, InstructionType: 1,
+ Args: [{ Name: 'N', Value: 12 }, { Name: 'LL', Value: 10 }, { Name: 'LH', Value: 85 }],
+ Script: //脚本
+ 'MYPSY:=COUNT(CLOSE>REF(CLOSE,1),N)/N*100;\n\
+ENTERLONG:CROSS(LL,MYPSY);\n\
+EXITLONG:CROSS(MYPSY,LH);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.TRADE_ROC = function ()
+{
+ let data =
+ {
+ Name: 'ROC', Description: '变动速率专家系统', IsMainIndex: true, InstructionType: 1,
+ Args: [{ Name: 'N', Value: 12 }, { Name: 'M', Value: 6 }],
+ Script: //脚本
+ 'WROC:=MA(100*(CLOSE-REF(CLOSE,N))/REF(CLOSE,N),M);\n\
+ENTERLONG:CROSS(WROC,0);\n\
+EXITLONG:CROSS(0,WROC);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.TRADE_RSI = function ()
+{
+ let data =
+ {
+ Name: 'RSI', Description: '相对强弱专家系统', IsMainIndex: true, InstructionType: 1,
+ Args: [{ Name: 'N', Value: 6 }, { Name: 'LL', Value: 20 }, { Name: 'LH', Value: 80 }],
+ Script: //脚本
+ 'LC:=REF(CLOSE,1);\n\
+WRSI:=SMA(MAX(CLOSE-LC,0),N,1)/SMA(ABS(CLOSE-LC),N,1)*100;\n\
+ENTERLONG:CROSS(WRSI,LL);\n\
+EXITLONG:CROSS(LH,WRSI);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.TRADE_VR = function ()
+{
+ let data =
+ {
+ Name: 'VR', Description: 'VR容量比率专家系统', IsMainIndex: true, InstructionType: 1,
+ Args: [{ Name: 'N', Value: 26 }, { Name: 'LL', Value: 70 }, { Name: 'LH', Value: 250 }],
+ Script: //脚本
+ 'WVR := SUM((IF(CLOSE>OPEN,VOL,0)+IF(CLOSE=OPEN,VOL/2,0)),N)/SUM((IF(CLOSE REF(VAR5, 1), VAR5,0), COLORRED, NODRAW;\n\
+洗盘: IF(VAR5 < REF(VAR5, 1), VAR5,0), COLORYELLOW, NODRAW;\n\
+STICKLINE(VAR5> REF(VAR5, 1),0, VAR5, 50, 0), COLORRED;\n\
+STICKLINE(VAR5 < REF(VAR5, 1), 0, VAR5, 50, 0), COLORYELLOW;'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.Zealink_Index2 = function ()
+{
+ let data =
+ {
+ Name: '牛熊区间', Description: '牛熊区间', IsMainIndex: false, YSpecificMaxMin: { Max: 100, Min: 1, Count: 4 }, YSplitScale: [1, 50, 100],
+ Args: [],
+ Script: //脚本
+'短高H:=(20*H+19*REF(H,1)+18*REF(H,2)+17*REF(H,3)+16*REF(H,4)+15*REF(H,5)+14*REF(H,6)\n\
++ 13 * REF(H, 7) + 12 * REF(H, 8) + 11 * REF(H, 9) + 10 * REF(H, 10) + 9 * REF(H, 11) + 8 * REF(H, 12)\n\
++ 7 * REF(H, 13) + 6 * REF(H, 14) + 5 * REF(H, 15) + 4 * REF(H, 16) + 3 * REF(H, 17) + 2 * REF(H, 18) +\n\
+REF(H, 20))/ 210, COLORBLUE, LINETHICK1;\n\
+短低L:= (20 * L + 19 * REF(L, 1) + 18 * REF(L, 2) + 17 * REF(L, 3) + 16 * REF(L, 4) + 15 * REF(L, 5) + 14 * REF(L, 6)\n\
++ 13 * REF(L, 7) + 12 * REF(L, 8) + 11 * REF(L, 9) + 10 * REF(L, 10) + 9 * REF(L, 11) + 8 * REF(L, 12)\n\
++ 7 * REF(L, 13) + 6 * REF(L, 14) + 5 * REF(L, 15) + 4 * REF(L, 16) + 3 * REF(L, 17) + 2 * REF(L, 18) +\n\
+REF(L, 20)) / 210, COLORBLUE, LINETHICK1;\n\
+D90H:= EMA(短高H, 90), COLORRED, LINETHICK1;\n\
+D90L:= EMA(短低L, 90), COLORRED, LINETHICK1;\n\
+D90差:= D90H - D90L;\n\
+D90顶:= D90H + D90差 * 2, COLORRED, LINETHICK1;\n\
+D90底:= D90L - D90差 * 2, COLORRED, LINETHICK1;\n\
+高0:= (EMA(EMA(H, 25), 25) - EMA(EMA(L, 25), 25)) * 1 + EMA(EMA(H, 25), 25), LINETHICK1, COLORWHITE;\n\
+低0:= EMA(EMA(L, 25), 25) - (EMA(EMA(H, 25), 25) - EMA(EMA(L, 25), 25)) * 1, LINETHICK1, COLORWHITE;\n\
+多头定位:= 低0 >= D90底 AND 高0 >= D90顶;\n\
+空头定位:= 高0 <= D90顶 AND 低0 <= D90底;\n\
+震荡定位:= 低0 >= D90底 AND 高0 <= D90顶;\n\
+牛市: IF(多头定位 == 1, 100, 1), COLORRED, NODRAW;\n\
+熊市: IF(空头定位 == 1, 100, 1), COLORGREEN, NODRAW;\n\
+震荡: IF(震荡定位 == 1, 100, 1), COLORGRAY, NODRAW;\n\
+STICKLINE(多头定位 == 1, 100, 1, 100, 0), COLORRED;\n\
+STICKLINE(空头定位 == 1, 100, 1, 100, 0), COLORGREEN;\n\
+STICKLINE(震荡定位 == 1, 100, 1, 100, 0), COLORGRAY;'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.Zealink_Index3 = function ()
+{
+ let data =
+ {
+ Name: '持仓信号', Description: '持仓信号', IsMainIndex: true,
+ Args: [],
+ Script: //脚本
+'买线:=EMA(C,2);\n\
+卖线:=EMA(SLOPE(C,30)*5+C,20); \n\
+BU:=CROSS(买线,卖线);\n\
+SEL:=CROSS(卖线,买线);\n\
+\n\
+STICKLINE(买线>=卖线 AND CLOSE>OPEN,LOW,HIGH,0,1),COLORRED;\n\
+STICKLINE(买线>=卖线 AND CLOSE=卖线 AND CLOSE>OPEN,CLOSE,OPEN,50,1),COLORRED;\n\
+STICKLINE(买线>=卖线 AND CLOSEOPEN,LOW,HIGH,0,1),COLORGREEN;\n\
+STICKLINE(买线<卖线 AND CLOSEOPEN,CLOSE,OPEN,50,1),COLORGREEN;\n\
+\n\
+HHJSJDA:=(3*CLOSE+OPEN+LOW+HIGH)/6;\n\
+HHJSJDB:=(19*HHJSJDA+19*REF(HHJSJDA,1)+18*REF(HHJSJDA,2)+17*REF(HHJSJDA,3)+16*REF(HHJSJDA,4)+15*REF(HHJSJDA,5)+14*REF(HHJSJDA,6)\n\
++13*REF(HHJSJDA,7)+12*REF(HHJSJDA,8)+11*REF(HHJSJDA,9)+10*REF(HHJSJDA,10)+9*REF(HHJSJDA,11)+8*REF(HHJSJDA,12)+7*REF(HHJSJDA,13)+6*REF(HHJSJDA,14)+5*REF(HHJSJDA,15)+4*REF(HHJSJDA,16)+3*REF(HHJSJDA,17)+2*REF\n\
+(HHJSJDA,20)+REF(HHJSJDA,19))/210,COLORYELLOW;\n\
+HHJSJDC:=MA(HHJSJDB,5),COLORRED;\n\
+快线:HHJSJDB,COLORYELLOW;\n\
+慢线:HHJSJDC,COLORRED;\n\
+\n\
+SVAR11:=HHV(HIGH,34);\n\
+SVAR14:=CLOSE-REF(CLOSE,1);\n\
+SVAR15:=MAX(SVAR14,0);\n\
+SVAR16:=ABS(SVAR14);\n\
+SVAR17:=SMA(SVAR15,7,1)/SMA(SVAR16,7,1)*100;\n\
+SVAR18:=SMA(SVAR15,13,1)/SMA(SVAR16,13,1)*100;\n\
+SVAR19:=BARSCOUNT(CLOSE);\n\
+SVAR20:=SMA(MAX(SVAR14,0),6,1)/SMA(ABS(SVAR14),6,1)*100;\n\
+SVAR21:=(-200)*(HHV(HIGH,60)-CLOSE)/(HHV(HIGH,60)-LLV(LOW,60))+100;\n\
+SVAR1A:=(CLOSE-LLV(LOW,15))/(HHV(HIGH,15)-LLV(LOW,15))*100;\n\
+SVAR1B:=SMA((SMA(SVAR1A,4,1)-50)*2,3,1);\n\
+SVAR1C:=(INDEXC-LLV(INDEXL,14))/(HHV(INDEXH,14)-LLV(INDEXL,14))*100;\n\
+SVAR1D:=SMA(SVAR1C,4,1);\n\
+SVAR1E:=SMA(SVAR1D,3,1);\n\
+SVAR1F:=(HHV(HIGH,30)-CLOSE)/CLOSE*100;\n\
+SVAR22:=SVAR20<=25 AND SVAR21<-95 AND SVAR1F>20 AND SVAR1B<-30 AND SVAR1E<30 AND SVAR11-CLOSE>=-0.25 AND SVAR17<22 AND SVAR18<28 AND SVAR19>50;\n\
+BUY3:=CROSS(SVAR22,0.5) AND COUNT(SVAR22==1,10)==1;\n\
+\n\
+SVARF:=LOW*0.9;\n\
+SVAR10X:=100-3*SMA((OPEN-LLV(LOW,75))/(HHV(HIGH,75)-LLV(LOW,75))*100,20,1)+2*SMA(SMA((OPEN-LLV(LOW,75))/(HHV(HIGH,75)-LLV(LOW,75))*100,20,1),15,1);\n\
+SVAR11X:=SVARF][REF(VOL,1) AND CLOSE>REF(CLOSE,1);\n\
+BUY2:=SVAR11X AND COUNT(SVAR11X,30)==1;\n\
+\n\
+VAR1:=(CLOSE+HIGH+LOW+OPEN)/4;\n\
+VAR2:=SUMBARS(VOL,CAPITAL);\n\
+VAR3:=HHV(VAR1,VAR2);\n\
+VAR4:=LLV(VAR1,VAR2);\n\
+VAR5:=(2*VAR1-VAR4-REF(VAR4,1))/(VAR3-VAR4);\n\
+VAR6:=(VAR1-VAR4)/(VAR3-VAR4);\n\
+VAR7:=IF(VAR1<=VAR4,VAR5*60,VAR6*60);\n\
+VAR8:=600*(EMA(CLOSE,3)-EMA(LOW,30))/EMA(LOW,30);\n\
+VAR9:=EMA(VAR8,7);\n\
+VARC:=HHV(HIGH,9)-LLV(LOW,9);\n\
+VARD:=HHV(HIGH,9)-CLOSE;\n\
+VARE:=CLOSE-LLV(LOW,9);\n\
+VARF:=VARD/VARC*100-70;\n\
+VAR10:=(CLOSE-LLV(LOW,60))/(HHV(HIGH,60)-LLV(LOW,60))*100;\n\
+VAR11:=(2*CLOSE+HIGH+LOW)/4;\n\
+VAR12:=SMA(VARE/VARC*100,3,1);\n\
+VAR13:=LLV(LOW,34);\n\
+VAR14:=SMA(VAR12,3,1)-SMA(VARF,9,1);\n\
+VAR15:=IF(VAR14>100,VAR14-100,0);\n\
+VAR16:=HHV(HIGH,34);\n\
+VAR17:=EMA((VAR11-VAR13)/(VAR16-VAR13)*100,8);\n\
+VAR18:=EMA(VAR17,5);\n\
+BUY:=STICKLINE(VAR17-VAR18>0,VAR17,VAR18,8,1),COLORRED;\n\
+SELL:=STICKLINE(VAR17-VAR18<0,VAR17,VAR18,8,1),COLORGREEN;\n\
+BUY1:=VAR17>VAR18 AND REF(VAR17,1)][REF(VAR18,1);\n\
+\n\
+短高H:=(20*H+19*REF(H,1)+18*REF(H,2)+17*REF(H,3)+16*REF(H,4)+15*REF(H,5)+14*REF(H,6)\n\
++13*REF(H,7)+12*REF(H,8)+11*REF(H,9)+10*REF(H,10)+9*REF(H,11)+8*REF(H,12)\n\
++7*REF(H,13)+6*REF(H,14)+5*REF(H,15)+4*REF(H,16)+3*REF(H,17)+2*REF(H,18)+\n\
+REF(H,20))/210,COLORBLUE,LINETHICK1;\n\
+短低L:=(20*L+19*REF(L,1)+18*REF(L,2)+17*REF(L,3)+16*REF(L,4)+15*REF(L,5)+14*REF(L,6)\n\
++13*REF(L,7)+12*REF(L,8)+11*REF(L,9)+10*REF(L,10)+9*REF(L,11)+8*REF(L,12)\n\
++7*REF(L,13)+6*REF(L,14)+5*REF(L,15)+4*REF(L,16)+3*REF(L,17)+2*REF(L,18)+\n\
+REF(L,20))/210,COLORBLUE,LINETHICK1;\n\
+D90H:=EMA(短高H,90),COLORRED,LINETHICK1;\n\
+D90L:=EMA(短低L,90),COLORRED,LINETHICK1;\n\
+D90差:=D90H-D90L;\n\
+D90顶:=D90H+D90差*2,COLORRED,LINETHICK1;\n\
+D90底:=D90L-D90差*2,COLORRED,LINETHICK1;\n\
+高0:=(EMA(EMA(H,25),25)-EMA(EMA(L,25),25))*1+EMA(EMA(H,25),25),LINETHICK1,COLORWHITE;\n\
+低0:=EMA(EMA(L,25),25)-(EMA(EMA(H,25),25)-EMA(EMA(L,25),25))*1,LINETHICK1,COLORWHITE;\n\
+多头定位:=低0>=D90底 AND 高0>=D90顶;\n\
+空头定位:=高0<=D90顶 AND 低0<=D90底;\n\
+震荡定位:=低0>=D90底 AND 高0<=D90顶;\n\
+\n\
+牛市:=多头定位==1;\n\
+熊市:=空头定位==1;\n\
+震荡:=震荡定位==1;\n\
+\n\
+非牛市:=熊市 OR 震荡;\n\
+非熊市:=牛市 OR 震荡;\n\
+\n\
+BUY11:=BUY1 AND 非熊市;\n\
+SELL11:=SELL1 AND 震荡定位==0;\n\
+\n\
+BUY111:=BUY11 AND COUNT(BUY11,10)<2;\n\
+BUY0:=BUY111 AND COUNT(BUY111,21)==1;\n\
+SELL111:=SELL11 AND COUNT(SELL11,10)<2;\n\
+SELL0:=SELL111 AND COUNT(SELL111,10)==1;\n\
+\n\
+XK1:=EMA(100*(CLOSE-LLV(LOW,34))/(HHV(HIGH,34)-LLV(LOW,34)),3)/4;\n\
+上穿:=REF(XK1,1)<5 AND XK1>=5;\n\
+BUY4:=上穿 AND COUNT(XK1<2,12)<1;\n\
+\n\
+SELL2:=REF(XK1,1)<=22.5 AND XK1>22.5 AND COUNT(REF(XK1,1)>=22.5 AND XK1<22.5,5)>0;\n\
+SELL3:=REF(XK1,1)>=21.5 AND XK1<21.5 AND COUNT(REF(XK1,1)>=22.5 AND XK1<22.5,12)>1;\n\
+SELL4:=SELL2 OR SELL3 AND COUNT((SELL2 OR SELL3)==1,5)==1;\n\
+\n\
+SUPERDRAWTEXT(BUY0,L,"机会",2,10),COLORRED;\n\
+SUPERDRAWTEXT(SELL0,H,"风险",1,10),COLORGREEN;\n\
+SUPERDRAWTEXT(BUY2,L,"机会",2,10),COLORRED;\n\
+SUPERDRAWTEXT(BUY4,L,"机会",2,10),COLORRED;\n\
+SUPERDRAWTEXT(SELL4,H,"风险",1,10),COLORGREEN;'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.Zealink_Index4 = function ()
+{
+ let data =
+ {
+ Name: '股东实际增减持', Description: '股东实际增减持', IsMainIndex: false, FloatPrecision: 0,
+ Args: [],
+ Script: //脚本
+'增持:NEWS(4),NODRAW,COLORRED;\n\
+减持:NEWS(5),NODRAW,COLORGREEN;\n\
+STICKLINE(增持>0,0,增持,1,0),COLORRED;\n\
+STICKLINE(减持<0,0,减持,1,0),COLORGREEN;'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.Zealink_Index5 = function ()
+{
+ let data =
+ {
+ Name: '大宗交易', Description: '大宗交易', IsMainIndex: false, FloatPrecision: 0,
+ Args: [],
+ Script: //脚本
+ '交易次数:NEWS(7);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.Zealink_Index6 = function ()
+{
+ let data =
+ {
+ Name: '信托持股', Description: '信托持股', IsMainIndex: false, FloatPrecision: 0,
+ Args: [],
+ Script: //脚本
+ '家数:NEWS(6);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.Zealink_Index7 = function () {
+ let data =
+ {
+ Name: '官网新闻', Description: '官网新闻', IsMainIndex: false, FloatPrecision: 0,
+ Args: [],
+ Script: //脚本
+ '个数:NEWS(8);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.Zealink_Index8 = function () {
+ let data =
+ {
+ Name: '高管要闻', Description: '高管要闻', IsMainIndex: false, FloatPrecision: 0,
+ Args: [],
+ Script: //脚本
+ '个数:NEWS(9);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.Zealink_Index9 = function ()
+{
+ let data =
+ {
+ Name: '股权质押', Description: '股权质押', IsMainIndex: false, FloatPrecision: 0,
+ Args: [],
+ Script: //脚本
+ '次数:NEWS(10);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.CJL = function ()
+{
+ let data =
+ {
+ Name: 'CJL', Description: '期货持仓量', IsMainIndex: false,
+ Args: [],
+ Script: //脚本
+ "成交量:VOL,VOLSTICK;\n\
+持仓量:VOLINSTK,LINEOVERLAY;"
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.SQJZ = function ()
+{
+ let data =
+ {
+ Name: 'SQJZ', Description: '神奇九转', IsMainIndex: true,
+ Script: //脚本
+"B:=C][=9 AND REFXV(COUNT(B,9),8)=9);\n\
+DRAWNUMBER(B1 AND REF(B,1)=0,L,1),COLORMAGENTA;\n\
+B2:=(N=5 AND REFXV(COUNT(B,6),4)=6) OR (N=6 AND REFXV(COUNT(B,7),5)=7) OR (N=7 AND REFXV(COUNT(B,8),6)=8) OR (N>=8 AND REFXV(COUNT(B,9),7)=9);\n\
+DRAWNUMBER(B2 AND REF(B,2)=0,L,2),COLORMAGENTA;\n\
+B8:=(N=1 AND COUNT(B,8)=8) OR (N>=2 AND REFXV(COUNT(B,9),1)=9);\n\
+DRAWNUMBER(B8 AND REF(B,8)=0,L,8),COLORMAGENTA;\n\
+B9:=(N>=1 AND COUNT(B,9)=9);\n\
+DRAWNUMBER(B9 AND REF(B,9)=0,L,9),COLORBROWN;\n\
+S:=C>REF(C,4);\n\
+S1:=(N=6 AND REFXV(COUNT(S,6),5)=6) OR (N=7 AND REFXV(COUNT(S,7),6)=7) OR (N=8 AND REFXV(COUNT(S,8),7)=8) OR (N>=9 AND REFXV(COUNT(S,9),8)=9);\n\
+DRAWNUMBER(S1 AND REF(S,1)=0,H,1),COLORMAGENTA,DRAWABOVE;\n\
+S2:=(N=5 AND REFXV(COUNT(S,6),4)=6) OR (N=6 AND REFXV(COUNT(S,7),5)=7) OR (N=7 AND REFXV(COUNT(S,8),6)=8) OR (N>=8 AND REFXV(COUNT(S,9),7)=9);\n\
+DRAWNUMBER(S2 AND REF(S,2)=0,H,2),COLORMAGENTA,DRAWABOVE;\n\
+S8:=(N=1 AND COUNT(S,8)=8) OR (N>=2 AND REFXV(COUNT(S,9),1)=9);\n\
+DRAWNUMBER(S8 AND REF(S,8)=0,H,8),COLORMAGENTA,DRAWABOVE;\n\
+S9:=(N>=1 AND COUNT(S,9)=9);\n\
+DRAWNUMBER(S9 AND REF(S,9)=0,H,9),COLORGREEN,DRAWABOVE;"
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.XT = function ()
+{
+ let data =
+ {
+ Name: 'XT', Description: '箱体', IsMainIndex: true,
+ Args: [{ Name: 'N', Value: 10 }],
+ Script: //脚本
+"【箱顶】:PEAK(CLOSE,N,1)*0.98;\n\
+【箱底】:TROUGH(CLOSE,N,1)*1.02;\n\
+【箱高】:100*(【箱顶】-【箱底】)/【箱底】,NODRAW;"
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.CFJT = function ()
+{
+ let data =
+ {
+ Name: 'CFJT', Description: '财富阶梯', IsMainIndex: true,
+ Script: //脚本
+"突破:=REF(EMA(C,14),1);\n\
+A1X:=(EMA(C,10)-突破)/突破*100;\n\
+多方:=IF(A1X>=0,REF(EMA(C,10),BARSLAST(CROSS(A1X,0))+1),DRAWNULL);\n\
+空方:=IF(A1X<0,REF(EMA(C,10),BARSLAST(CROSS(0,A1X))+1),DRAWNULL);\n\
+STICKLINE(A1X>=0,多方,突破,110,0),COLORRED;\n\
+STICKLINE(A1X<0,空方,突破,110,0),COLORGREEN;"
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.CYX = function ()
+{
+ let data =
+ {
+ Name: 'CYX', Description: '撑压线', IsMainIndex: true,
+ Args: [{ Name: 'N', Value: 7 }],
+ Script: //脚本
+"Z1:=STRCAT(HYBLOCK,' ');\n\
+Z2:=STRCAT(Z1,DYBLOCK);\n\
+Z3:=STRCAT(Z2,' ');\n\
+DRAWTEXT_FIX(ISLASTBAR,0,0,0,STRCAT(Z3,GNBLOCK)),COLOR00C0C0;\n\
+A1:=REF(H,N)=HHV(H,2*N+1);\n\
+B1:=FILTER(A1,N);\n\
+C1:=BACKSET(B1,N+1);\n\
+D1:=FILTER(C1,N);\n\
+A2:=REF(L,N)=LLV(L,2*N+1);\n\
+B2:=FILTER(A2,N);\n\
+C2:=BACKSET(B2,N+1);\n\
+D2:=FILTER(C2,N);\n\
+E1:=(REF(LLV(L,2*N),1)+REF(HHV(H,2*N),1))/2;\n\
+E2:=(H+L)/2;\n\
+H1:=(D1 AND NOT(D2 AND E1>=E2)) OR ISLASTBAR OR BARSCOUNT(C)=1;\n\
+L1:=(D2 AND NOT(D1 AND E1=E2);\n\
+X1:=REF(BARSLAST(H1),1)+1;\n\
+F1:=BACKSET(H1 AND COUNT(L1,X1)>0,LLVBARS(IF(L1,L,10000),X1));\n\
+G1:=F1>REF(F1,1);\n\
+I1:=BACKSET(G1,2);\n\
+LD:=I1>REF(I1,1);\n\
+L2:=LD OR ISLASTBAR OR BARSCOUNT(C)=1;\n\
+X2:=REF(BARSLAST(L2),1)+1;\n\
+F2:=BACKSET(L2 AND COUNT(H2,X2)>0,HHVBARS(IF(H2,H,0),X2));\n\
+G2:=F2>REF(F2,1);\n\
+I2:=BACKSET(G2,2);\n\
+HD:=I2>REF(I2,1);\n\
+R1:=BACKSET(ISLASTBAR,BARSLAST(HD)+1);\n\
+S1:=R1>REF(R1,1);\n\
+T1:=BACKSET(ISLASTBAR,BARSLAST(LD)+1);\n\
+U1:=T1>REF(T1,1);\n\
+R2:=BACKSET(S1,REF(BARSLAST(HD),1)+2);\n\
+S2:=R2>REF(R2,1);\n\
+T2:=BACKSET(U1,REF(BARSLAST(LD),1)+2);\n\
+U2:=T2>REF(T2,1);\n\
+DRAWLINE(S2,H,S1,H,1),LINETHICK2,COLORRED;\n\
+DRAWLINE(U2,L,U1,L,1),LINETHICK2,COLORGREEN;"
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.WAVE = function ()
+{
+ let data =
+ {
+ Name: 'WAVE', Description: '波浪分析', IsMainIndex: true,
+ Args: [{ Name: 'N', Value: 5 }],
+ Script: //脚本
+"ZIG(3,N);"
+ };
+
+ return data;
+}
+
+
+module.exports =
+{
+ JSCommonIndexScript:
+ {
+ JSIndexScript: JSIndexScript
+ }
+};
+
+
+
diff --git a/uni_modules/jones-hqchart2/js_sdk/umychart.index.wechat.js b/uni_modules/jones-hqchart2/js_sdk/umychart.index.wechat.js
new file mode 100644
index 0000000..069159a
--- /dev/null
+++ b/uni_modules/jones-hqchart2/js_sdk/umychart.index.wechat.js
@@ -0,0 +1,1119 @@
+/*
+ copyright (c) 2018 jones
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ 开源项目 https://github.com/jones2000/HQChart
+
+ jones_2000@163.com
+
+ 指标基类及定制指标
+*/
+
+import {
+ JSCommonResource_Global_JSChartResource as g_JSChartResource,
+} from './umychart.resource.wechat.js'
+
+import { JSCommonComplier } from "./umychart.complier.wechat.js"; //通达信编译器
+
+//图形库
+import {
+ JSCommonChartPaint_IChartPainting as IChartPainting,
+ JSCommonChartPaint_ChartSingleText as ChartSingleText,
+ JSCommonChartPaint_ChartKLine as ChartKLine,
+ JSCommonChartPaint_ChartLine as ChartLine,
+ JSCommonChartPaint_ChartSubLine as ChartSubLine,
+ JSCommonChartPaint_ChartPointDot as ChartPointDot,
+ JSCommonChartPaint_ChartStick as ChartStick,
+ JSCommonChartPaint_ChartLineStick as ChartLineStick,
+ JSCommonChartPaint_ChartStickLine as ChartStickLine,
+ JSCommonChartPaint_ChartOverlayKLine as ChartOverlayKLine,
+ JSCommonChartPaint_ChartMinuteInfo as ChartMinuteInfo,
+ JSCommonChartPaint_ChartRectangle as ChartRectangle,
+ JSCommonChartPaint_ChartMultiText as ChartMultiText,
+ JSCommonChartPaint_ChartMultiLine as ChartMultiLine,
+ JSCommonChartPaint_ChartMultiBar as ChartMultiBar,
+ JSCommonChartPaint_ChartPie as ChartPie,
+ JSCommonChartPaint_ChartCircle as ChartCircle,
+ JSCommonChartPaint_ChartChinaMap as ChartChinaMap,
+ JSCommonChartPaint_ChartRadar as ChartRadar,
+ JSCommonChartPaint_ChartCorssCursor as ChartCorssCursor,
+ JSCommonChartPaint_ChartBuySell as ChartBuySell,
+ JSCommonChartPaint_ChartMACD as ChartMACD,
+ JSCommonChartPaint_ChartSplashPaint as ChartSplashPaint,
+ JSCommonChartPaint_ChartBackground as ChartBackground,
+ JSCommonChartPaint_ChartMinuteVolumBar as ChartMinuteVolumBar,
+ JSCommonChartPaint_ChartMultiHtmlDom as ChartMultiHtmlDom,
+ JSCommonChartPaint_ChartLock as ChartLock,
+ JSCommonChartPaint_ChartVolStick as ChartVolStick,
+ JSCommonChartPaint_ChartBand as ChartBand,
+} from "./umychart.chartpaint.wechat.js";
+
+import
+{
+ JSCommonSplit_CoordinateInfo as CoordinateInfo,
+ JSCommonSplit_IFrameSplitOperator as IFrameSplitOperator,
+ JSCommonSplit_FrameSplitKLinePriceY as FrameSplitKLinePriceY,
+ JSCommonSplit_FrameSplitY as FrameSplitY,
+ JSCommonSplit_FrameSplitKLineX as FrameSplitKLineX,
+ JSCommonSplit_FrameSplitMinutePriceY as FrameSplitMinutePriceY,
+ JSCommonSplit_FrameSplitMinuteX as FrameSplitMinuteX,
+ JSCommonSplit_FrameSplitXData as FrameSplitXData,
+ JSCommonSplit_SplitData as SplitData,
+ JSCommonSplit_PriceSplitData as PriceSplitData,
+} from './umychart.framesplit.wechat.js'
+
+import
+{
+ JSCommonChartTitle_IChartTitlePainting as IChartTitlePainting,
+ JSCommonChartTitle_DynamicKLineTitlePainting as DynamicKLineTitlePainting,
+ JSCommonChartTitle_DynamicMinuteTitlePainting as DynamicMinuteTitlePainting,
+ JSCommonChartTitle_DynamicChartTitlePainting as DynamicChartTitlePainting,
+ JSCommonChartTitle_DynamicTitleData as DynamicTitleData,
+ JSCommonChartTitle_STRING_FORMAT_TYPE as STRING_FORMAT_TYPE,
+} from './umychart.charttitle.wechat.js'
+//////////////////////////////////////////////////////////
+//
+// 指标信息
+//
+function IndexInfo(name, param)
+{
+ this.Name = name; //名字
+ this.Param = param; //参数
+ this.LineColor; //线段颜色
+ this.ReqeustData = null; //数据请求
+}
+
+function BaseIndex(name)
+ {
+ this.Index; //指标阐述
+ this.Name = name; //指标名字
+ this.UpdateUICallback; //数据到达回调
+
+ //默认创建都是线段
+ this.Create = function (hqChart, windowIndex)
+ {
+ for (var i in this.Index)
+ {
+ if (!this.Index[i].Name) continue;
+
+ var maLine = new ChartLine();
+ maLine.Canvas = hqChart.Canvas;
+ maLine.Name = this.Name + '-' + i.toString();
+ maLine.ChartBorder = hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder;
+ maLine.ChartFrame = hqChart.Frame.SubFrame[windowIndex].Frame;
+ maLine.Color = this.Index[i].LineColor;
+
+ hqChart.ChartPaint.push(maLine);
+ }
+ }
+
+ //指标不支持 周期/复权/股票等
+ this.NotSupport = function (hqChart, windowIndex, message)
+ {
+ var paint = hqChart.GetChartPaint(windowIndex);
+ for (var i in paint)
+ {
+ paint[i].Data.Data = []; //清空数据
+ if (i == 0) paint[i].NotSupportMessage = message;
+ }
+ }
+
+ //格式化指标名字+参数
+ //格式:指标名(参数1,参数2,参数3,...)
+ this.FormatIndexTitle = function ()
+ {
+ var title = this.Name;
+ var param = null;
+
+ for (var i in this.Index)
+ {
+ var item = this.Index[i];
+ if (item.Param == null) continue;
+
+ if (param) param += ',' + item.Param.toString();
+ else param = item.Param.toString();
+ }
+
+ if (param) title += '(' + param + ')';
+
+ return title;
+ }
+
+ this.InvokeUpdateUICallback = function (paint)
+ {
+ if (typeof (this.UpdateUICallback) != 'function') return;
+
+ let indexData = new Array();
+ for (let i in paint)
+ {
+ indexData.push({ Name: this.Index[i].Name, Data: paint[i].Data });
+ }
+
+ this.UpdateUICallback(indexData);
+ }
+}
+
+//脚本指标
+//name=指标名字 args=参数名字 参数值
+function ScriptIndex(name, script, args, option)
+{
+ this.newMethod = BaseIndex; //派生
+ this.newMethod(name);
+ delete this.newMethod;
+
+ this.Script = script;
+ this.Arguments = [];
+ this.OutVar = [];
+ this.ID; //指标ID
+ this.FloatPrecision = 2; //小数位数
+ this.StringFormat;
+ this.KLineType = null; //K线显示类型
+ this.InstructionType; //五彩K线, 交易指标
+ this.YSpecificMaxMin = null; //最大最小值
+ this.YSplitScale = null; //固定刻度
+ this.OutName=null; //动态输出指标名字
+
+ //指标上锁配置信息
+ this.IsLocked = false; //是否锁住指标
+ this.LockCallback = null;
+ this.LockID = null;
+ this.LockBG = null; //锁背景色
+ this.LockTextColor = null;
+ this.LockText = null;
+ this.LockFont = null;
+ this.LockCount = 10;
+
+ if (option)
+ {
+ if (option.FloatPrecision >= 0) this.FloatPrecision = option.FloatPrecision;
+ if (option.StringFormat > 0) this.StringFormat = option.StringFormat;
+ if (option.ID) this.ID = option.ID;
+ if (option.KLineType) this.KLineType = option.KLineType;
+ if (option.InstructionType) this.InstructionType = option.InstructionType;
+ if (option.YSpecificMaxMin) this.YSpecificMaxMin = option.YSpecificMaxMin;
+ if (option.YSplitScale) this.YSplitScale = option.YSplitScale;
+ if (option.OutName) this.OutName=option.OutName;
+ }
+
+ if (option && option.Lock)
+ {
+ if (option.Lock.IsLocked == true) this.IsLocked = true; //指标上锁
+ if (option.Lock.Callback) this.LockCallback = option.Lock.Callback; //锁回调
+ if (option.Lock.ID) this.LockID = option.Lock.ID; //锁ID
+ if (option.Lock.BG) this.LockBG = option.Lock.BG;
+ if (option.Lock.TextColor) this.LockTextColor = option.Lock.TextColor;
+ if (option.Lock.Text) this.LockText = option.Lock.Text;
+ if (option.Lock.Font) this.LockFont = option.Lock.Font;
+ if (option.Lock.Count) this.LockCount = option.Lock.Count;
+ }
+
+ if (args) this.Arguments = args;
+
+ this.SetLock = function (lockData) {
+ if (lockData.IsLocked == true) {
+ this.IsLocked = true; //指标上锁
+ if (lockData.Callback) this.LockCallback = lockData.Callback; //锁回调
+ if (lockData.ID) this.LockID = lockData.ID; //锁ID
+ if (lockData.BG) this.LockBG = lockData.BG;
+ if (lockData.TextColor) this.LockTextColor = lockData.TextColor;
+ if (lockData.Text) this.LockText = lockData.Text;
+ if (lockData.Font) this.LockFont = lockData.Font;
+ if (lockData.Count) this.LockCount = lockData.Count;
+ }
+ else { //清空锁配置信息
+ this.IsLocked = false; //是否锁住指标
+ this.LockCallback = null;
+ this.LockID = null;
+ this.LockBG = null; //锁背景色
+ this.LockTextColor = null;
+ this.LockText = null;
+ this.LockFont = null;
+ this.LockCount = 10;
+ }
+ }
+
+ this.ExecuteScript = function (hqChart, windowIndex, hisData)
+ {
+ this.OutVar = [];
+ let self = this;
+ let param =
+ {
+ HQChart: hqChart,
+ WindowIndex: windowIndex,
+ HistoryData: hisData,
+ Self: this
+ };
+
+ let hqDataType = 0; //默认K线
+ if (hqChart.ClassName === 'MinuteChartContainer') hqDataType = 2; //分钟数据
+ let option =
+ {
+ HQDataType: hqDataType,
+ Symbol: hqChart.Symbol,
+ Data: hisData,
+ SourceData: hqChart.SourceData, //原始数据
+ Callback: this.RecvResultData, CallbackParam: param,
+ Async: true,
+ MaxReqeustDataCount: hqChart.MaxReqeustDataCount,
+ MaxRequestMinuteDayCount: hqChart.MaxRequestMinuteDayCount,
+ Arguments: this.Arguments
+ };
+
+ if (hqChart.NetworkFilter) option.NetworkFilter = hqChart.NetworkFilter;
+
+ let code = this.Script;
+ let run = JSCommonComplier.JSComplier.Execute(code, option, hqChart.ScriptErrorCallback);
+ }
+
+ this.RecvResultData = function (outVar, param)
+ {
+ let hqChart = param.HQChart;
+ let windowIndex = param.WindowIndex;
+ let hisData = param.HistoryData;
+ param.Self.OutVar = outVar;
+ param.Self.BindData(hqChart, windowIndex, hisData);
+
+ if (param.Self.IsLocked == false) //不上锁
+ {
+ param.HQChart.Frame.SubFrame[windowIndex].Frame.SetLock(null);
+ }
+ else //上锁
+ {
+ let lockData =
+ {
+ IsLocked: true, Callback: param.Self.LockCallback, IndexName: param.Self.Name, ID: param.Self.LockID,
+ BG: param.Self.LockBG, Text: param.Self.LockText, TextColor: param.Self.LockTextColor, Font: param.Self.LockFont,
+ Count: param.Self.LockCount
+ };
+ param.HQChart.Frame.SubFrame[windowIndex].Frame.SetLock(lockData);
+ }
+
+ param.HQChart.UpdataDataoffset(); //更新数据偏移
+ param.HQChart.UpdateFrameMaxMin(); //调整坐标最大 最小值
+ param.HQChart.Draw();
+
+ var event = hqChart.GetIndexEvent(); //指标计算完成回调
+ if (event)
+ {
+ var self = param.Self;
+ var data = {
+ OutVar: self.OutVar, WindowIndex: windowIndex, Name: self.Name, Arguments: self.Arguments, HistoryData: hisData,
+ Stock: { Symbol: hqChart.Symbol, Name: hqChart.Name }
+ };
+ event.Callback(event, data, self);
+ }
+ }
+
+ this.CreateLine = function (hqChart, windowIndex, varItem, id)
+ {
+ let line = new ChartLine();
+ line.Canvas = hqChart.Canvas;
+ line.DrawType = 1; //无效数不画
+ line.Name = varItem.Name;
+ line.ChartBorder = hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder;
+ line.ChartFrame = hqChart.Frame.SubFrame[windowIndex].Frame;
+ if (varItem.Color) line.Color = this.GetColor(varItem.Color);
+ else line.Color = this.GetDefaultColor(id);
+ if (varItem.IsShow==false) line.IsShow=false;
+ if (varItem.LineWidth)
+ {
+ let width = parseInt(varItem.LineWidth.replace("LINETHICK", ""));
+ if (!isNaN(width) && width > 0) line.LineWidth = width;
+ }
+
+ if (varItem.IsDotLine) line.IsDotLine = true; //虚线
+ if (varItem.IsShow == false) line.IsShow = false;
+
+ let titleIndex = windowIndex + 1;
+ line.Data.Data = varItem.Data;
+ if (varItem.IsShowTitle===false) //NOTEXT 不绘制标题
+ {
+ }
+ else if (IFrameSplitOperator.IsString(varItem.Name) && varItem.Name.indexOf("NOTEXT")==0) //标题中包含NOTEXT不绘制标题
+ {
+ }
+ else
+ {
+ hqChart.TitlePaint[titleIndex].Data[id] = new DynamicTitleData(line.Data, (varItem.NoneName==true? null: varItem.Name) , line.Color);
+ }
+
+ hqChart.ChartPaint.push(line);
+ }
+
+ this.CreateOverlayLine = function (hqChart, windowIndex, varItem, id)
+ {
+ let line = new ChartSubLine();
+ line.Canvas = hqChart.Canvas;
+ line.DrawType = 1; //无效数不画
+ line.Name = varItem.Name;
+ line.ChartBorder = hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder;
+ line.ChartFrame = hqChart.Frame.SubFrame[windowIndex].Frame;
+ if (varItem.Color) line.Color = this.GetColor(varItem.Color);
+ else line.Color = this.GetDefaultColor(id);
+
+ if (varItem.LineWidth) {
+ let width = parseInt(varItem.LineWidth.replace("LINETHICK", ""));
+ if (!isNaN(width) && width > 0) line.LineWidth = width;
+ }
+
+ if (varItem.IsDotLine) line.IsDotLine = true; //虚线
+ if (varItem.IsShow == false) line.IsShow = false;
+
+ let titleIndex = windowIndex + 1;
+ line.Data.Data = varItem.Data;
+ hqChart.TitlePaint[titleIndex].Data[id] = new DynamicTitleData(line.Data, varItem.Name, line.Color);
+
+ hqChart.ChartPaint.push(line);
+ }
+
+ //创建柱子
+ this.CreateBar = function (hqChart, windowIndex, varItem, id)
+ {
+ let bar = new ChartStickLine();
+ bar.Canvas = hqChart.Canvas;
+ if (varItem.Draw.Width > 0) bar.LineWidth = varItem.Draw.Width;
+ else bar.LineWidth=1;
+
+ bar.Name = varItem.Name;
+ bar.ChartBorder = hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder;
+ bar.ChartFrame = hqChart.Frame.SubFrame[windowIndex].Frame;
+ if (varItem.Color) bar.Color = this.GetColor(varItem.Color);
+ else bar.Color = this.GetDefaultColor(id);
+
+ let titleIndex = windowIndex + 1;
+ bar.Data.Data = varItem.Draw.DrawData;
+ bar.BarType = varItem.Draw.Type;
+
+ //hqChart.TitlePaint[titleIndex].Data[id]=new DynamicTitleData(bar.Data,varItem.Name,bar.Color);
+
+ hqChart.ChartPaint.push(bar);
+ }
+
+ //创建文本
+ this.CreateText = function (hqChart, windowIndex, varItem, id)
+ {
+ let chartText = new ChartSingleText();
+ chartText.Canvas = hqChart.Canvas;
+ chartText.TextAlign='left';
+
+ chartText.Name = varItem.Name;
+ chartText.ChartBorder = hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder;
+ chartText.ChartFrame = hqChart.Frame.SubFrame[windowIndex].Frame;
+ chartText.ReloadResource();
+
+ if (varItem.Color) chartText.Color = this.GetColor(varItem.Color);
+ else chartText.Color = this.GetDefaultColor(id);
+
+ let titleIndex = windowIndex + 1;
+ if (varItem.Draw.Position) chartText.Position=varItem.Draw.Position; //赋值坐标
+ if (varItem.Draw.DrawData) chartText.Data.Data = varItem.Draw.DrawData;
+ chartText.Text = varItem.Draw.Text;
+ if (varItem.Draw.Direction > 0) chartText.Direction = varItem.Draw.Direction;
+ if (varItem.Draw.YOffset > 0) chartText.YOffset = varItem.Draw.YOffset;
+ if (varItem.Draw.TextAlign) chartText.TextAlign = varItem.Draw.TextAlign;
+
+ //hqChart.TitlePaint[titleIndex].Data[id]=new DynamicTitleData(bar.Data,varItem.Name,bar.Color);
+ hqChart.ChartPaint.push(chartText);
+ }
+
+ //COLORSTICK
+ this.CreateMACD = function (hqChart, windowIndex, varItem, id)
+ {
+ let chartMACD = new ChartMACD();
+ chartMACD.Canvas = hqChart.Canvas;
+
+ chartMACD.Name = varItem.Name;
+ chartMACD.ChartBorder = hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder;
+ chartMACD.ChartFrame = hqChart.Frame.SubFrame[windowIndex].Frame;
+ if (varItem.LineWidth)
+ {
+ var width=parseInt(varItem.LineWidth.replace("LINETHICK",""));
+ if (!isNaN(width) && width>0) chartMACD.LineWidth=width;
+ }
+
+ let titleIndex = windowIndex + 1;
+ chartMACD.Data.Data = varItem.Data;
+ var clrTitle=this.GetDefaultColor(id);
+ if (varItem.Color) clrTitle= this.GetColor(varItem.Color);
+ hqChart.TitlePaint[titleIndex].Data[id] = new DynamicTitleData(chartMACD.Data, varItem.Name, clrTitle);
+
+ hqChart.ChartPaint.push(chartMACD);
+ }
+
+ this.CreatePointDot = function (hqChart, windowIndex, varItem, id) {
+ let pointDot = new ChartPointDot();
+ pointDot.Canvas = hqChart.Canvas;
+ pointDot.Name = varItem.Name;
+ pointDot.ChartBorder = hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder;
+ pointDot.ChartFrame = hqChart.Frame.SubFrame[windowIndex].Frame;
+ if (varItem.Color) pointDot.Color = this.GetColor(varItem.Color);
+ else pointDot.Color = this.GetDefaultColor(id);
+
+ if (varItem.Radius) pointDot.Radius = varItem.Radius;
+
+ if (varItem.LineWidth) {
+ let width = parseInt(varItem.LineWidth.replace("LINETHICK", ""));
+ if (!isNaN(width) && width > 0) pointDot.Radius = width;
+ }
+
+ let titleIndex = windowIndex + 1;
+ pointDot.Data.Data = varItem.Data;
+ hqChart.TitlePaint[titleIndex].Data[id] = new DynamicTitleData(pointDot.Data, varItem.Name, pointDot.Color);
+
+ hqChart.ChartPaint.push(pointDot);
+ }
+
+ this.CreateStick = function (hqChart, windowIndex, varItem, id) {
+ let chart = new ChartStick();
+ chart.Canvas = hqChart.Canvas;
+ chart.Name = varItem.Name;
+ chart.ChartBorder = hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder;
+ chart.ChartFrame = hqChart.Frame.SubFrame[windowIndex].Frame;
+ if (varItem.Color) chart.Color = this.GetColor(varItem.Color);
+ else chart.Color = this.GetDefaultColor(id);
+
+ if (varItem.LineWidth) {
+ let width = parseInt(varItem.LineWidth.replace("LINETHICK", ""));
+ if (!isNaN(width) && width > 0) chart.LineWidth = width;
+ }
+
+ let titleIndex = windowIndex + 1;
+ chart.Data.Data = varItem.Data;
+ hqChart.TitlePaint[titleIndex].Data[id] = new DynamicTitleData(chart.Data, varItem.Name, chart.Color);
+
+ hqChart.ChartPaint.push(chart);
+ }
+
+ this.CreateLineStick = function (hqChart, windowIndex, varItem, id) {
+ let chart = new ChartLineStick();
+ chart.Canvas = hqChart.Canvas;
+ chart.Name = varItem.Name;
+ chart.ChartBorder = hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder;
+ chart.ChartFrame = hqChart.Frame.SubFrame[windowIndex].Frame;
+ if (varItem.Color) chart.Color = this.GetColor(varItem.Color);
+ else chart.Color = this.GetDefaultColor(id);
+
+ if (varItem.LineWidth) {
+ let width = parseInt(varItem.LineWidth.replace("LINETHICK", ""));
+ if (!isNaN(width) && width > 0) chart.LineWidth = width;
+ }
+
+ let titleIndex = windowIndex + 1;
+ chart.Data.Data = varItem.Data;
+ hqChart.TitlePaint[titleIndex].Data[id] = new DynamicTitleData(chart.Data, varItem.Name, chart.Color);
+
+ hqChart.ChartPaint.push(chart);
+ }
+
+ this.CreateStraightLine = function (hqChart, windowIndex, varItem, id) {
+ let line = new ChartLine();
+ line.DrawType = 1;
+ line.Canvas = hqChart.Canvas;
+ line.Name = varItem.Name;
+ line.ChartBorder = hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder;
+ line.ChartFrame = hqChart.Frame.SubFrame[windowIndex].Frame;
+ if (varItem.Color) line.Color = this.GetColor(varItem.Color);
+ else line.Color = this.GetDefaultColor(id);
+
+ if (varItem.LineWidth) {
+ let width = parseInt(varItem.LineWidth.replace("LINETHICK", ""));
+ if (!isNaN(width) && width > 0) line.LineWidth = width;
+ }
+
+ let titleIndex = windowIndex + 1;
+ line.Data.Data = varItem.Draw.DrawData;
+ //hqChart.TitlePaint[titleIndex].Data[id]=new DynamicTitleData(line.Data,varItem.Name,line.Color);
+
+ hqChart.ChartPaint.push(line);
+ }
+
+ this.CreateVolStick = function (hqChart, windowIndex, varItem, id, hisData) {
+ let chart = new ChartVolStick();
+ chart.Canvas = hqChart.Canvas;
+ chart.Name = varItem.Name;
+ chart.ChartBorder = hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder;
+ chart.ChartFrame = hqChart.Frame.SubFrame[windowIndex].Frame;
+ chart.KLineDrawType = hqChart.KLineDrawType; //设置K线显示类型
+ if (varItem.Color) chart.Color = this.GetColor(varItem.Color);
+ else chart.Color = this.GetDefaultColor(id);
+
+ let titleIndex = windowIndex + 1;
+ chart.Data.Data = varItem.Data;
+ chart.HistoryData = hisData;
+ hqChart.TitlePaint[titleIndex].Data[id] = new DynamicTitleData(chart.Data, varItem.Name, chart.Color);
+
+ hqChart.ChartPaint.push(chart);
+ }
+
+ this.CreateBand = function (hqChart, windowIndex, varItem, id) {
+ let chart = new ChartBand();
+ chart.Canvas = hqChart.Canvas;
+ chart.Name = varItem.Name;
+ chart.ChartBorder = hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder;
+ chart.ChartFrame = hqChart.Frame.SubFrame[windowIndex].Frame;
+
+ chart.FirstColor = varItem.Draw.Color[0];
+ chart.SecondColor = varItem.Draw.Color[1];
+ chart.Data.Data = varItem.Draw.DrawData;
+
+ hqChart.ChartPaint.push(chart);
+ }
+
+ this.CreatePolyLine = function (hqChart, windowIndex, varItem, id) {
+ let line = new ChartLine();
+ line.Canvas = hqChart.Canvas;
+ line.Name = varItem.Name;
+ line.ChartBorder = hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder;
+ line.ChartFrame = hqChart.Frame.SubFrame[windowIndex].Frame;
+ if (varItem.Color) line.Color = this.GetColor(varItem.Color);
+ else line.Color = this.GetDefaultColor(id);
+
+ if (varItem.LineWidth) {
+ let width = parseInt(varItem.LineWidth.replace("LINETHICK", ""));
+ if (!isNaN(width) && width > 0) line.LineWidth = width;
+ }
+
+ let titleIndex = windowIndex + 1;
+ line.Data.Data = varItem.Draw.DrawData;
+ //hqChart.TitlePaint[titleIndex].Data[id] = new DynamicTitleData(line.Data, ' ', line.Color); //给一个空的标题
+
+ hqChart.ChartPaint.push(line);
+ }
+
+ //创建K线图
+ this.CreateKLine = function (hqChart, windowIndex, varItem, id) {
+ let chart = new ChartKLine();
+ chart.Canvas = hqChart.Canvas;
+ chart.Name = varItem.Name;
+ chart.ChartBorder = hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder;
+ chart.ChartFrame = hqChart.Frame.SubFrame[windowIndex].Frame;
+
+ chart.Data.Data = varItem.Draw.DrawData;
+ chart.IsShowMaxMinPrice = false;
+
+ if (varItem.Color) //如果设置了颜色,使用外面设置的颜色
+ chart.UnchagneColor = chart.DownColor = chart.UpColor = this.GetColor(varItem.Color);
+
+ hqChart.ChartPaint.push(chart);
+ }
+
+ this.CreateNumberText = function (hqChart, windowIndex, varItem, id) {
+ let chartText = new ChartSingleText();
+ chartText.Canvas = hqChart.Canvas;
+
+ chartText.Name = varItem.Name;
+ chartText.ChartBorder = hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder;
+ chartText.ChartFrame = hqChart.Frame.SubFrame[windowIndex].Frame;
+ chartText.ReloadResource();
+
+ chartText.TextAlign="center";
+ if (varItem.Color) chartText.Color = this.GetColor(varItem.Color);
+ else chartText.Color = this.GetDefaultColor(id);
+ if (varItem.IsDrawAbove) chartText.Direction=1;
+ else chartText.Direction=2;
+
+ let titleIndex = windowIndex + 1;
+ chartText.Data.Data = varItem.Draw.DrawData.Value;
+ chartText.Text = varItem.Draw.DrawData.Text;
+
+ //hqChart.TitlePaint[titleIndex].Data[id]=new DynamicTitleData(bar.Data,varItem.Name,bar.Color);
+ hqChart.ChartPaint.push(chartText);
+ }
+
+ //创建图标
+ this.CreateIcon = function (hqChart, windowIndex, varItem, id) {
+ let chartText = new ChartSingleText();
+ chartText.Canvas = hqChart.Canvas;
+ chartText.TextAlign = 'center';
+
+ chartText.Name = varItem.Name;
+ chartText.ChartBorder = hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder;
+ chartText.ChartFrame = hqChart.Frame.SubFrame[windowIndex].Frame;
+
+ let titleIndex = windowIndex + 1;
+ chartText.Data.Data = varItem.Draw.DrawData;
+ chartText.Text = varItem.Draw.Icon.Symbol;
+ if (varItem.Color) chartText.Color = this.GetColor(varItem.Color);
+ else if (varItem.Draw.Icon.Color) chartText.Color = varItem.Draw.Icon.Color;
+ else chartText.Color = 'rgb(0,0,0)';
+
+ //hqChart.TitlePaint[titleIndex].Data[id]=new DynamicTitleData(bar.Data,varItem.Name,bar.Color);
+
+ hqChart.ChartPaint.push(chartText);
+ }
+
+ this.CreateRectangle = function (hqChart, windowIndex, varItem, i)
+ {
+ let chart = new ChartRectangle();
+ chart.Canvas = hqChart.Canvas;
+ chart.Name = varItem.Name;
+ chart.ChartBorder = hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder;
+ chart.ChartFrame = hqChart.Frame.SubFrame[windowIndex].Frame;
+
+ chart.Color = [varItem.Draw.DrawData.Color];
+ chart.Rect = varItem.Draw.DrawData.Rect;
+ if (varItem.Color) chart.BorderColor = this.GetColor(varItem.Color);
+ hqChart.ChartPaint.push(chart);
+ }
+
+ this.CreateBackgroud=function(hqChart,windowIndex,varItem,id)
+ {
+ let chart=new ChartBackground();
+ chart.Canvas=hqChart.Canvas;
+ chart.Name=varItem.Name;
+ chart.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder;
+ chart.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame;
+ if (varItem.Draw && varItem.Draw.DrawData)
+ {
+ var drawData=varItem.Draw.DrawData;
+ chart.Color=drawData.Color;
+ chart.ColorAngle=drawData.Angle;
+
+ if (drawData.Data) chart.Data.Data=drawData.Data;
+ }
+
+ hqChart.ChartPaint.push(chart);
+ }
+
+ this.CreateMultiText = function (hqChart, windowIndex, varItem, i)
+ {
+ let chart = new ChartMultiText();
+ chart.Canvas = hqChart.Canvas;
+ chart.Name = varItem.Name;
+ chart.ChartBorder = hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder;
+ chart.ChartFrame = hqChart.Frame.SubFrame[windowIndex].Frame;
+
+ chart.Data = hqChart.ChartPaint[0].Data;//绑定K线
+ chart.Texts = varItem.Draw.DrawData;
+ hqChart.ChartPaint.push(chart);
+ }
+
+ this.CreateMulitHtmlDom=function(hqChart,windowIndex,varItem,i)
+ {
+ let chart=new ChartMultiHtmlDom();
+ chart.Canvas=hqChart.Canvas;
+ chart.Name=varItem.Name;
+ chart.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder;
+ chart.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame;
+
+ chart.Data=hqChart.ChartPaint[0].Data;//绑定K线
+ chart.Texts=varItem.Draw.DrawData;
+ chart.DrawCallback= varItem.Draw.Callback;
+ hqChart.ChartPaint.push(chart);
+ }
+
+ this.CreateMultiLine = function (hqChart, windowIndex, varItem, i)
+ {
+ let chart = new ChartMultiLine();
+ chart.Canvas = hqChart.Canvas;
+ chart.Name = varItem.Name;
+ chart.ChartBorder = hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder;
+ chart.ChartFrame = hqChart.Frame.SubFrame[windowIndex].Frame;
+
+ chart.Data = hqChart.ChartPaint[0].Data;//绑定K线
+ chart.Lines = varItem.Draw.DrawData;
+
+ if (varItem.Draw.LineDash) chart.LineDash=varItem.Draw.LineDash;
+ if (IFrameSplitOperator.IsNumber(varItem.Draw.LineWidth)) chart.LineWidth=varItem.Draw.LineWidth;
+
+ hqChart.ChartPaint.push(chart);
+ }
+
+ this.CreateMultiBar = function (hqChart, windowIndex, varItem, i)
+ {
+ let chart = new ChartMultiBar();
+ chart.Canvas = hqChart.Canvas;
+ chart.Name = varItem.Name;
+ chart.ChartBorder = hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder;
+ chart.ChartFrame = hqChart.Frame.SubFrame[windowIndex].Frame;
+
+ chart.Data = hqChart.ChartPaint[0].Data;//绑定K线
+ chart.Bars = varItem.Draw.DrawData;
+ hqChart.ChartPaint.push(chart);
+ }
+
+ //创建K线背景
+ this.CreateSelfKLine = function (hqChart, windowIndex, hisData)
+ {
+ let chart = new ChartKLine();
+ chart.Canvas = hqChart.Canvas;
+ chart.Name = "Self Kline"
+ chart.ChartBorder = hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder;
+ chart.ChartFrame = hqChart.Frame.SubFrame[windowIndex].Frame;
+
+ chart.Data = hisData
+ chart.IsShowMaxMinPrice = false;
+ chart.IsShowKTooltip = false;
+ chart.DrawType = this.KLineType;
+
+ hqChart.ChartPaint.push(chart);
+ }
+
+ this.BindInstructionData = function (hqChart, windowIndex, hisData) //绑定指示指标
+ {
+ if (this.OutVar == null || this.OutVar.length < 0) return;
+ if (this.InstructionType == 2)
+ {
+ let varItem = this.OutVar[this.OutVar.length - 1]; //取最后一组数据作为指示数据
+ hqChart.SetInstructionData(this.InstructionType, { Data: varItem.Data }); //设置指示数据
+ return true;
+ }
+ else if (this.InstructionType == 1) //交易系统
+ {
+ var buyData, sellData;
+ for (var i in this.OutVar)
+ {
+ let item = this.OutVar[i];
+ if (item.Name == 'ENTERLONG') buyData = item.Data;
+ else if (item.Name == 'EXITLONG') sellData = item.Data;
+ }
+
+ hqChart.SetInstructionData(this.InstructionType, { Buy: buyData, Sell: sellData }); //设置指示数据
+ return true;
+ }
+ }
+
+
+ this.BindData = function (hqChart, windowIndex, hisData)
+ {
+ if (windowIndex == 0 && this.InstructionType)
+ {
+ this.BindInstructionData(hqChart, windowIndex, hisData);
+ return;
+ }
+
+ //清空指标图形
+ hqChart.DeleteIndexPaint(windowIndex);
+ if (windowIndex == 0) hqChart.ShowKLine(true);
+
+ if (this.OutVar == null || this.OutVar.length < 0) return;
+
+ //叠加一个K线背景
+ if (this.KLineType != null)
+ {
+ if (this.KLineType === 0 || this.KLineType === 1 || this.KLineType === 2) this.CreateSelfKLine(hqChart, windowIndex, hisData);
+ else if (this.KLineType === -1 && windowIndex == 0) hqChart.ShowKLine(false);
+ }
+
+ if (windowIndex >= 1 && hqChart.Frame)
+ {
+ hqChart.Frame.SubFrame[windowIndex].Frame.YSplitOperator.FloatPrecision = this.FloatPrecision;
+ if (this.YSpecificMaxMin) hqChart.Frame.SubFrame[windowIndex].Frame.YSpecificMaxMin = this.YSpecificMaxMin; //最大最小值
+ if (this.YSplitScale) hqChart.Frame.SubFrame[windowIndex].Frame.YSplitScale = this.YSplitScale; //固定刻度
+ }
+
+ for (let i in this.OutVar)
+ {
+ let item = this.OutVar[i];
+ if (item.IsExData === true) continue; //扩展数据不显示图形
+ if (item.Type==1000 || item.Type==1001) continue; //数据集合, 字符串
+
+ if (item.Type == 0)
+ {
+ if (item.IsOverlayLine) this.CreateOverlayLine(hqChart, windowIndex, item, i);
+ else this.CreateLine(hqChart, windowIndex, item, i);
+ }
+ else if (item.Type == 1)
+ {
+ switch (item.Draw.DrawType)
+ {
+ case 'STICKLINE':
+ this.CreateBar(hqChart, windowIndex, item, i);
+ break;
+ case 'DRAWTEXT':
+ case 'SUPERDRAWTEXT':
+ case 'DRAWTEXT_FIX':
+ this.CreateText(hqChart, windowIndex, item, i);
+ break;
+ case 'DRAWLINE':
+ this.CreateStraightLine(hqChart, windowIndex, item, i);
+ break;
+ case 'DRAWBAND':
+ this.CreateBand(hqChart, windowIndex, item, i);
+ break;
+ case 'DRAWKLINE':
+ this.CreateKLine(hqChart, windowIndex, item, i);
+ break;
+ case 'DRAWKLINE_IF':
+ this.CreateKLine(hqChart, windowIndex, item, i);
+ break;
+ case 'POLYLINE':
+ this.CreatePolyLine(hqChart, windowIndex, item, i);
+ break;
+ case 'DRAWNUMBER':
+ this.CreateNumberText(hqChart, windowIndex, item, i);
+ break;
+ case 'DRAWICON':
+ this.CreateIcon(hqChart, windowIndex, item, i);
+ break;
+ case 'DRAWRECTREL':
+ this.CreateRectangle(hqChart, windowIndex, item, i);
+ break;
+ case 'DRAWGBK':
+ case "DRAWGBK2":
+ this.CreateBackgroud(hqChart,windowIndex,item,i);
+ break;
+
+ //第3方指标定制
+ case 'MULTI_TEXT':
+ this.CreateMultiText(hqChart, windowIndex, item, i);
+ break;
+ case "MULTI_HTMLDOM":
+ this.CreateMulitHtmlDom(hqChart,windowIndex,item,i);
+ break;
+ case 'MULTI_LINE':
+ this.CreateMultiLine(hqChart, windowIndex, item, i);
+ break;
+ case 'MULTI_BAR':
+ this.CreateMultiBar(hqChart, windowIndex, item, i);
+ break;
+ case "KLINE_BG":
+ this.CreateBackgroud(hqChart,windowIndex,item,i);
+ break;
+ }
+ }
+ else if (item.Type == 2)
+ {
+ this.CreateMACD(hqChart, windowIndex, item, i);
+ }
+ else if (item.Type == 3)
+ {
+ this.CreatePointDot(hqChart, windowIndex, item, i);
+ }
+ else if (item.Type == 4)
+ {
+ this.CreateLineStick(hqChart, windowIndex, item, i);
+ }
+ else if (item.Type == 5)
+ {
+ this.CreateStick(hqChart, windowIndex, item, i);
+ }
+ else if (item.Type == 6)
+ {
+ this.CreateVolStick(hqChart, windowIndex, item, i, hisData);
+ }
+
+ var titlePaint = hqChart.TitlePaint[windowIndex + 1];
+ if (titlePaint && titlePaint.Data && i < titlePaint.Data.length) //设置标题数值 小数位数和格式
+ {
+ if (this.StringFormat > 0) titlePaint.Data[i].StringFormat = this.StringFormat;
+ if (this.FloatPrecision >= 0) titlePaint.Data[i].FloatPrecision = this.FloatPrecision;
+ if (this.OutName && this.OutName.length>0 && this.Arguments && this.Arguments.length>0)
+ {
+ titlePaint.SetDynamicOutName(this.OutName,this.Arguments);
+ }
+ }
+ }
+
+ let titleIndex = windowIndex + 1;
+ hqChart.TitlePaint[titleIndex].Title = this.Name;
+
+ let indexParam = '';
+ for (let i in this.Arguments)
+ {
+ let item = this.Arguments[i];
+ if (indexParam.length > 0) indexParam += ',';
+ indexParam += item.Value.toString();
+ }
+
+ if (indexParam.length > 0) hqChart.TitlePaint[titleIndex].Title = this.Name + '(' + indexParam + ')';
+
+ if (hqChart.UpdateUICallback) hqChart.UpdateUICallback('ScriptIndex', this.OutVar,
+ { WindowIndex: windowIndex, Name: this.Name, Arguments: this.Arguments, HistoryData: hisData }); //通知上层回调
+
+ return true;
+ }
+
+
+ this.GetDefaultColor = function (id) //给一个默认的颜色
+ {
+ let COLOR_ARRAY = g_JSChartResource.ColorArray;
+ let number = parseInt(id);
+ return COLOR_ARRAY[number % (COLOR_ARRAY.length - 1)];
+ }
+
+
+ this.GetColor = function (colorName) //获取颜色
+ {
+ let COLOR_MAP = new Map([
+ ['COLORBLACK', 'rgb(0,0,0)'],
+ ['COLORBLUE', 'rgb(18,95,216)'],
+ ['COLORGREEN', 'rgb(25,158,0)'],
+ ['COLORCYAN', 'rgb(0,255,198)'],
+ ['COLORRED', 'rgb(238,21,21)'],
+ ['COLORMAGENTA', 'rgb(255,0,222)'],
+ ['COLORBROWN', 'rgb(149,94,15)'],
+ ['COLORLIGRAY', 'rgb(218,218,218)'], //画淡灰色
+ ['COLORGRAY', 'rgb(133,133,133)'], //画深灰色
+ ['COLORLIBLUE', 'rgb(94,204,255)'], //淡蓝色
+ ['COLORLIGREEN', 'rgb(183,255,190)'], //淡绿色
+ ['COLORLICYAN', 'rgb(154,255,242)'], //淡青色
+ ['COLORLIRED', 'rgb(255,172,172)'], //淡红色
+ ['COLORLIMAGENTA', 'rgb(255,145,241)'], //淡洋红色
+ ['COLORWHITE', 'rgb(255,255,255)'], //白色
+ ['COLORYELLOW', 'rgb(255,198,0)']
+ ]);
+
+ if (COLOR_MAP.has(colorName)) return COLOR_MAP.get(colorName);
+
+ //COLOR 自定义色
+ //格式为COLOR+“RRGGBB”:RR、GG、BB表示红色、绿色和蓝色的分量,每种颜色的取值范围是00-FF,采用了16进制。
+ //例如:MA5:MA(CLOSE,5),COLOR00FFFF 表示纯红色与纯绿色的混合色:COLOR808000表示淡蓝色和淡绿色的混合色。
+ if (colorName.indexOf('COLOR') == 0) return '#' + colorName.substr(5);
+ return 'rgb(30,144,255)';
+ }
+}
+
+
+
+
+
+//市场多空
+function MarketLongShortIndex()
+{
+ this.newMethod = BaseIndex; //派生
+ this.newMethod('市场多空');
+ delete this.newMethod;
+
+ this.Index = new Array(
+ new IndexInfo("多空指标", null),
+ new IndexInfo("多头区域", null),
+ new IndexInfo("空头区域", null)
+ );
+
+ this.Index[0].LineColor = g_JSChartResource.Index.LineColor[0];
+ this.Index[1].LineColor = g_JSChartResource.UpBarColor;
+ this.Index[2].LineColor = g_JSChartResource.DownBarColor;
+
+ this.LongShortData; //多空数据
+
+ this.Create = function (hqChart, windowIndex) {
+ for (var i in this.Index) {
+ var paint = null;
+ if (i == 0)
+ paint = new ChartLine();
+ else
+ paint = new ChartStraightLine();
+
+ paint.Color = this.Index[i].LineColor;
+ paint.Canvas = hqChart.Canvas;
+ paint.Name = this.Name + "-" + i.toString();
+ paint.ChartBorder = hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder;
+ paint.ChartFrame = hqChart.Frame.SubFrame[windowIndex].Frame;
+
+ hqChart.ChartPaint.push(paint);
+ }
+ }
+
+ //请求数据
+ this.RequestData = function (hqChart, windowIndex, hisData) {
+ var self = this;
+ var param =
+ {
+ HQChart: hqChart,
+ WindowIndex: windowIndex,
+ HistoryData: hisData
+ };
+
+ this.LongShortData = [];
+
+ if (param.HQChart.Period > 0) //周期数据
+ {
+ this.NotSupport(param.HQChart, param.WindowIndex, "不支持周期切换");
+ param.HQChart.Draw();
+ return false;
+ }
+
+ //请求数据
+ wx.request({
+ url: g_JSChartResource.Index.MarketLongShortApiUrl,
+ data:
+ {
+
+ },
+ method: 'POST',
+ dataType: "json",
+ async: true,
+ success: function (recvData) {
+ self.RecvData(recvData, param);
+ }
+ });
+
+ return true;
+ }
+
+ this.RecvData = function (recvData, param) {
+ if (recvData.data.data.length <= 0) return;
+
+ var aryData = new Array();
+ for (var i in recvData.data.data) {
+ var item = recvData.data.data[i];
+ var indexData = new SingleData();
+ indexData.Date = item[0];
+ indexData.Value = item[1];
+ aryData.push(indexData);
+ }
+
+ var aryFittingData = param.HistoryData.GetFittingData(aryData);
+
+ var bindData = new ChartData();
+ bindData.Data = aryFittingData;
+ bindData.Period = param.HQChart.Period; //周期
+ bindData.Right = param.HQChart.Right; //复权
+
+ this.LongShortData = bindData.GetValue();
+ this.BindData(param.HQChart, param.WindowIndex, param.HistoryData);
+
+ param.HQChart.UpdataDataoffset(); //更新数据偏移
+ param.HQChart.UpdateFrameMaxMin(); //调整坐标最大 最小值
+ param.HQChart.Draw();
+
+ }
+
+
+ this.BindData = function (hqChart, windowIndex, hisData) {
+ var paint = hqChart.GetChartPaint(windowIndex);
+
+ if (paint.length != this.Index.length) return false;
+
+ //paint[0].Data.Data=SWLData;
+ paint[0].Data.Data = this.LongShortData;
+ paint[0].NotSupportMessage = null;
+ paint[1].Data.Data[0] = 8;
+ paint[2].Data.Data[0] = 1;
+
+ //指定[0,9]
+ hqChart.Frame.SubFrame[windowIndex].Frame.YSpecificMaxMin = { Max: 9, Min: 0, Count: 3 };
+
+ var titleIndex = windowIndex + 1;
+
+ for (var i in paint) {
+ hqChart.TitlePaint[titleIndex].Data[i] = new DynamicTitleData(paint[i].Data, this.Index[i].Name, this.Index[i].LineColor);
+ if (i > 0) hqChart.TitlePaint[titleIndex].Data[i].DataType = "StraightLine";
+ }
+
+ hqChart.TitlePaint[titleIndex].Title = this.FormatIndexTitle();
+
+ if (hqChart.UpdateUICallback) hqChart.UpdateUICallback('MarketLongShortIndex', paint, { WindowIndex: windowIndex, HistoryData: hisData }); //通知上层回调
+ return true;
+ }
+
+}
+
+
+
+module.exports =
+{
+ JSCommonIndex:
+ {
+ IndexInfo: IndexInfo,
+ BaseIndex: BaseIndex,
+ ScriptIndex:ScriptIndex,
+ },
+
+ //单个类导出
+ JSCommonIndex_IndexInfo: IndexInfo,
+ JSCommonIndex_BaseIndex: BaseIndex,
+ JSCommonIndex_ScriptIndex:ScriptIndex,
+};
diff --git a/uni_modules/jones-hqchart2/js_sdk/umychart.klineinfo.wechat.js b/uni_modules/jones-hqchart2/js_sdk/umychart.klineinfo.wechat.js
new file mode 100644
index 0000000..2c62a8c
--- /dev/null
+++ b/uni_modules/jones-hqchart2/js_sdk/umychart.klineinfo.wechat.js
@@ -0,0 +1,702 @@
+/*
+ copyright (c) 2018 jones
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ 开源项目 https://github.com/jones2000/HQChart
+
+ jones_2000@163.com
+
+ 小程序信息地雷数据
+*/
+
+import {
+ JSCommonResource_Global_JSChartResource as g_JSChartResource,
+} from './umychart.resource.wechat.js'
+
+var KLINE_INFO_TYPE=
+{
+ INVESTOR:1, //互动易
+ ANNOUNCEMENT:2, //公告
+ PFORECAST:3, //业绩预告
+
+ ANNOUNCEMENT_QUARTER_1:4, //一季度报
+ ANNOUNCEMENT_QUARTER_2:5, //半年报
+ ANNOUNCEMENT_QUARTER_3:6, //2季度报
+ ANNOUNCEMENT_QUARTER_4:7, //年报
+
+ RESEARCH:8, //调研
+ BLOCKTRADING:9, //大宗交易
+ TRADEDETAIL:10, //龙虎榜
+
+ POLICY:11 //策略信息
+}
+
+function KLineInfoData()
+{
+ this.ID;
+ this.Date;
+ this.Title;
+ this.InfoType;
+ this.ExtendData; //扩展数据
+}
+
+/*
+ 信息地雷
+ 信息地雷列表
+*/
+function JSKLineInfoMap()
+{
+}
+
+JSKLineInfoMap.Get=function(id)
+{
+ var infoMap=new Map(
+ [
+ ["互动易", {Create:function(){ return new InvestorInfo()} }],
+ ["公告", {Create:function(){ return new AnnouncementInfo()} }],
+ ["业绩预告", {Create:function(){ return new PforecastInfo()} }],
+ ["调研", {Create:function(){ return new ResearchInfo()} }],
+ ["大宗交易", {Create:function(){ return new BlockTrading()} }],
+ ["龙虎榜", {Create:function(){ return new TradeDetail()} }],
+ ["策略选股", {Create: function () { return new PolicyInfo() } }]
+ ]
+ );
+
+ return infoMap.get(id);
+}
+
+function IKLineInfo()
+{
+ this.MaxReqeustDataCount=1000;
+ this.StartDate=20160101;
+ this.Data;
+
+ this.GetToday=function()
+ {
+ var date=new Date();
+ var today=date.getFullYear()*10000+(date.getMonth()+1)*100+date.getDate();
+ return today;
+ }
+}
+
+/*
+ 互动易
+*/
+function InvestorInfo()
+{
+ this.newMethod=IKLineInfo; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.RequestData=function(hqChart)
+ {
+ var self = this;
+ var param={ HQChart:hqChart };
+ this.Data=[];
+
+ //请求数据
+ wx.request({
+ url: g_JSChartResource.Domain+g_JSChartResource.KLine.Info.Investor.ApiUrl,
+ data:
+ {
+ "filed": ["question","answerdate","symbol","id"],
+ "symbol": [param.HQChart.Symbol],
+ "querydate":{"StartDate":this.StartDate,"EndDate":this.GetToday()},
+ "start":0,
+ "end":this.MaxReqeustDataCount,
+ },
+ method:"post",
+ dataType: "json",
+ success: function (recvData)
+ {
+ self.RecvData(recvData,param);
+ }
+ });
+
+ return true;
+ }
+
+ this.RecvData=function(recvData,param)
+ {
+ var data=recvData.data;
+ if (!data || !data.list || data.list.length<=0) return;
+
+ for (var i in data.list)
+ {
+ var item = data.list[i];
+ var infoData=new KLineInfoData();
+ infoData.Date=item.answerdate;
+ infoData.Title=item.question;
+ infoData.InfoType=KLINE_INFO_TYPE.INVESTOR;
+ this.Data.push(infoData);
+ }
+
+ param.HQChart.UpdataChartInfo();
+ param.HQChart.Draw();
+ }
+}
+
+/*
+ 公告
+*/
+function AnnouncementInfo()
+{
+ this.newMethod=IKLineInfo; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.RequestData=function(hqChart)
+ {
+ var self = this;
+ var param={ HQChart:hqChart };
+ this.Data=[];
+
+ //请求数据
+ wx.request({
+ url: g_JSChartResource.Domain+g_JSChartResource.KLine.Info.Announcement.ApiUrl,
+ data:
+ {
+ "filed": ["title","releasedate","symbol","id"],
+ "symbol": [param.HQChart.Symbol],
+ "querydate":{"StartDate":this.StartDate,"EndDate":this.GetToday()},
+ "start":0,
+ "end":this.MaxReqeustDataCount,
+ },
+ method:"post",
+ dataType: "json",
+ success: function (recvData)
+ {
+ self.RecvData(recvData,param);
+ }
+ });
+
+ return true;
+ }
+
+ this.RecvData=function(recvData,param)
+ {
+ var data=recvData.data;
+ if (!data) return;
+ if (!data.report || data.report.length<=0) return;
+
+ for (var i in data.report)
+ {
+ var item = data.report[i];
+ var infoData=new KLineInfoData();
+ infoData.Date=item.releasedate;
+ infoData.Title=item.title;
+ infoData.InfoType=KLINE_INFO_TYPE.ANNOUNCEMENT;
+ for(var j in item.type)
+ {
+ var typeItem=item.type[j];
+ switch(typeItem)
+ {
+ case "一季度报告":
+ infoData.InfoType=KLINE_INFO_TYPE.ANNOUNCEMENT_QUARTER_1;
+ break;
+ case "半年度报告":
+ infoData.InfoType=KLINE_INFO_TYPE.ANNOUNCEMENT_QUARTER_2;
+ break;
+ case "三季度报告":
+ infoData.InfoType=KLINE_INFO_TYPE.ANNOUNCEMENT_QUARTER_3;
+ break;
+ case "年度报告":
+ infoData.InfoType=KLINE_INFO_TYPE.ANNOUNCEMENT_QUARTER_4;
+ break;
+ }
+ }
+ this.Data.push(infoData);
+ }
+
+ param.HQChart.UpdataChartInfo();
+ param.HQChart.Draw();
+ }
+}
+
+
+/*
+ 业绩预告
+*/
+function PforecastInfo()
+{
+ this.newMethod=IKLineInfo; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.RequestData=function(hqChart)
+ {
+ var self = this;
+ this.Data = [];
+ var param={ HQChart:hqChart };
+
+ //请求数据
+ wx.request({
+ url: g_JSChartResource.Domain+g_JSChartResource.KLine.Info.Pforecast.ApiUrl,
+ data:
+ {
+ "field": ["pforecast.type","pforecast.reportdate","fweek"],
+ "condition":
+ [
+ {"item":["pforecast.reportdate","int32","gte",this.StartDate]}
+ ],
+ "symbol": [param.HQChart.Symbol],
+ "start":0,
+ "end":this.MaxReqeustDataCount,
+ },
+ method:"post",
+ dataType: "json",
+ success: function (recvData)
+ {
+ self.RecvData(recvData,param);
+ }
+ });
+ return true;
+ }
+
+ this.RecvData=function(recvData,param)
+ {
+ var data=recvData.data;
+ if (!data.stock || data.stock.length!=1) return;
+ if (!data.stock[0].stockday || data.stock[0].stockday.length<=0) return;
+
+ for (var i in data.stock[0].stockday)
+ {
+ var item = data.stock[0].stockday[i];
+ if (item.pforecast.length>0)
+ {
+ var dataItem=item.pforecast[0];
+ var infoData=new KLineInfoData();
+ infoData.Date= item.date;
+ infoData.Title=dataItem.type;
+ infoData.InfoType=KLINE_INFO_TYPE.PFORECAST;
+ infoData.ExtendData={ Type:dataItem.type, ReportDate:dataItem.reportdate}
+ if(item.fweek) //未来周涨幅
+ {
+ infoData.ExtendData.FWeek={};
+ if (item.fweek.week1!=null) infoData.ExtendData.FWeek.Week1=item.fweek.week1;
+ if (item.fweek.week4!=null) infoData.ExtendData.FWeek.Week4=item.fweek.week4;
+ }
+ this.Data.push(infoData);
+ }
+ }
+
+ param.HQChart.UpdataChartInfo();
+ param.HQChart.Draw();
+ }
+}
+
+/*
+ 投资者关系 (调研)
+*/
+function ResearchInfo()
+{
+ this.newMethod=IKLineInfo; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.RequestData=function(hqChart)
+ {
+ var self = this;
+ var param= { HQChart:hqChart };
+
+ this.Data=[];
+
+ //请求数据
+ wx.request({
+ url: g_JSChartResource.Domain+g_JSChartResource.KLine.Info.Research.ApiUrl,
+ data:
+ {
+ "filed": ["releasedate","researchdate","level","symbol","id"],
+ "querydate":{"StartDate":this.StartDate,"EndDate":this.GetToday()},
+ "symbol": [param.HQChart.Symbol],
+ "start":0,
+ "end":this.MaxReqeustDataCount,
+ },
+ method:"post",
+ dataType: "json",
+ success: function (recvData)
+ {
+ self.RecvData(recvData,param);
+ }
+ });
+
+ return true;
+ }
+
+ this.RecvData=function(recvData,param)
+ {
+ var data=recvData.data;
+ if (!data) return;
+ if (!data.list || data.list.length<=0) return;
+
+ for (var i in data.list)
+ {
+ var item = data.list[i];
+ var infoData=new KLineInfoData();
+ infoData.ID=item.id;
+ infoData.Date= item.researchdate;
+ infoData.InfoType=KLINE_INFO_TYPE.RESEARCH;
+ infoData.ExtendData={ Level:item.level };
+ this.Data.push(infoData);
+
+ }
+
+ param.HQChart.UpdataChartInfo();
+ param.HQChart.Draw();
+ }
+}
+
+/*
+ 大宗交易
+*/
+function BlockTrading()
+{
+ this.newMethod=IKLineInfo; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.RequestData=function(hqChart)
+ {
+ var self = this;
+ var param={ HQChart:hqChart,};
+ this.Data=[];
+
+ //请求数据
+ wx.request({
+ url: g_JSChartResource.Domain+g_JSChartResource.KLine.Info.BlockTrading.ApiUrl,
+ data:
+ {
+ "field": ["blocktrading.price","blocktrading.vol","blocktrading.premium","fweek","price"],
+ "condition":
+ [
+ {"item":["date","int32","gte",this.StartDate]},
+ {"item":["blocktrading.vol","int32","gte","0"]}
+ ],
+ "symbol": [param.HQChart.Symbol],
+ "start":0,
+ "end":this.MaxReqeustDataCount,
+ },
+ method:"post",
+ dataType: "json",
+ success: function (recvData)
+ {
+ self.RecvData(recvData,param);
+ }
+ });
+
+ return true;
+ }
+
+ this.RecvData=function(recvData,param)
+ {
+ var data=recvData.data;
+ if (!data || !data.stock || data.stock.length!=1) return;
+ if (!data.stock[0].stockday || data.stock[0].stockday.length<=0) return;
+
+ for (var i in data.stock[0].stockday)
+ {
+ var item = data.stock[0].stockday[i];
+ var infoData=new KLineInfoData();
+ infoData.Date= item.date;
+ infoData.InfoType=KLINE_INFO_TYPE.BLOCKTRADING;
+ infoData.ExtendData=
+ {
+ Price:item.blocktrading.price, //交易价格
+ Premium:item.blocktrading.premium, //溢价 (百分比%)
+ Vol:item.blocktrading.vol, //交易金额单位(万元)
+ ClosePrice:item.price, //收盘价
+ };
+
+ if(item.fweek) //未来周涨幅
+ {
+ infoData.ExtendData.FWeek={};
+ if (item.fweek.week1!=null) infoData.ExtendData.FWeek.Week1=item.fweek.week1;
+ if (item.fweek.week4!=null) infoData.ExtendData.FWeek.Week4=item.fweek.week4;
+ }
+
+ this.Data.push(infoData);
+ }
+
+ param.HQChart.UpdataChartInfo();
+ param.HQChart.Draw();
+ }
+}
+
+
+/*
+ 龙虎榜
+*/
+function TradeDetail()
+{
+ this.newMethod=IKLineInfo; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.RequestData=function(hqChart)
+ {
+ var self = this;
+ var param={ HQChart:hqChart };
+
+ this.Data=[];
+
+ //请求数据
+ wx.request({
+ url: g_JSChartResource.Domain+g_JSChartResource.KLine.Info.TradeDetail.ApiUrl,
+ data:
+ {
+ "field": ["tradedetail.typeexplain","tradedetail.type","fweek"],
+ "condition":
+ [
+ {"item":["date","int32","gte",this.StartDate]},
+ {"item":["tradedetail.type","int32","gte","0"]}
+ ],
+ "symbol": [param.HQChart.Symbol],
+ "start":0,
+ "end":this.MaxReqeustDataCount,
+ },
+ method:"post",
+ dataType: "json",
+ success: function (recvData)
+ {
+ self.RecvData(recvData,param);
+ }
+ });
+
+ return true;
+ }
+
+ this.RecvData=function(recvData,param)
+ {
+ var data=recvData.data;
+ if (!data || !data.stock || data.stock.length!=1) return;
+ if (!data.stock[0].stockday || data.stock[0].stockday.length<=0) return;
+
+ for (var i in data.stock[0].stockday)
+ {
+ var item = data.stock[0].stockday[i];
+
+ var infoData=new KLineInfoData();
+ infoData.Date= item.date;
+ infoData.InfoType=KLINE_INFO_TYPE.TRADEDETAIL;
+ infoData.ExtendData={Detail:new Array()};
+
+ for(var j in item.tradedetail)
+ {
+ var tradeItem=item.tradedetail[j];
+ infoData.ExtendData.Detail.push({"Type":tradeItem.type,"TypeExplain":tradeItem.typeexplain});
+ }
+
+ if(item.fweek) //未来周涨幅
+ {
+ infoData.ExtendData.FWeek={};
+ if (item.fweek.week1!=null) infoData.ExtendData.FWeek.Week1=item.fweek.week1;
+ if (item.fweek.week4!=null) infoData.ExtendData.FWeek.Week4=item.fweek.week4;
+ }
+
+ this.Data.push(infoData);
+ }
+
+ param.HQChart.UpdataChartInfo();
+ param.HQChart.Draw();
+ }
+}
+
+//策略信息
+function PolicyInfo()
+{
+ this.newMethod = IKLineInfo; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.PolicyList = []; //筛选的策略名字 {Name:策略名, Guid:策略的GUID}
+
+ this.SetPolicyList=function(aryPolicy)
+ {
+ for(let i in aryPolicy)
+ {
+ this.PolicyList.push({Name:aryPolicy[i]});
+ }
+ }
+
+ this.RequestData = function (hqChart)
+ {
+ var self = this;
+ this.Data = [];
+ var param = { HQChart: hqChart };
+
+ // setTimeout(function () { self.RecvData(null, param); }, 2000); //模拟数据到达
+
+ //请求数据
+ wx.request({
+ url: g_JSChartResource.Domain + g_JSChartResource.KLine.Info.Policy.ApiUrl,
+ data: {
+ "symbol": [param.HQChart.Symbol],
+ field: ["policy"],
+ "condition": [
+ { "item": ["date", "int32", "gte", this.StartDate, "lte", this.GetToday()] }],
+ "start": 0,
+ "end": this.MaxReqeustDataCount
+ },
+ method: "post",
+ dataType: "json",
+ success: function (recvData) {
+ self.RecvData(recvData, param);
+ }
+
+ })
+
+ return true;
+ }
+
+ this.RecvData = function (recvData, param)
+ {
+ var data = recvData.data;
+ if (!data.stock || data.stock.length != 1) return;
+ if (!data.stock[0].stockday || data.stock[0].stockday.length <= 0) return;
+
+ var setName=new Set();
+ for(var i in this.PolicyList) //把需要过滤的策略名字放set里, 方便后面过滤
+ {
+ setName.add(this.PolicyList[i].Name);
+ }
+
+ for (var i in data.stock[0].stockday)
+ {
+ var item = data.stock[0].stockday[i];
+ var infoData = new KLineInfoData();
+ infoData.Date = item.date;
+ infoData.InfoType = KLINE_INFO_TYPE.POLICY;
+ infoData.ExtendData = [];
+ for (var j in item.policy)
+ {
+ var name = item.policy[j].name;
+ if (setName.has(name)) infoData.ExtendData.push({ Name: name });
+ }
+
+ if (infoData.ExtendData.length>0) this.Data.push(infoData);
+ }
+
+ param.HQChart.UpdataChartInfo();
+ param.HQChart.Draw();
+
+ if (param.HQChart.UpdateUICallback) param.HQChart.UpdateUICallback('RecvPolicyInfoData', this);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////
+// 走势图信息地雷
+//
+//
+////////////////////////////////////////////////////////////////////////////////////////////
+function JSMinuteInfoMap() { }
+
+JSMinuteInfoMap.InfoMap = new Map(
+[
+ ["大盘异动", { Create: function () { return new MarketEventInfo() } }],
+]);
+
+JSMinuteInfoMap.Get = function (id)
+{
+ return JSMinuteInfoMap.InfoMap.get(id);
+}
+
+function IMinuteInfo()
+{
+ this.Data;
+ this.ClassName = 'IMinuteInfo';
+}
+
+//////////////////////////////////////////////////////////////////////
+// 大盘异动
+// 结构 {Date:日期 Time:时间, Title:标题, Type:0 }
+////////////////////////////////////////////////////////////////////
+function MarketEventInfo()
+{
+ this.newMethod = IMinuteInfo; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.ClassName = 'MarketEventInfo';
+
+ this.RequestData = function (hqChart)
+ {
+ var self = this;
+ this.Data = [];
+ var param =
+ {
+ HQChart: hqChart
+ };
+
+ var url = g_JSChartResource.CacheDomain + '/cache/analyze/shszevent/marketevent/concept/' + hqChart.TradeDate + '.json';
+
+ if (hqChart.NetworkFilter) {
+ var obj =
+ {
+ Name: 'MarketEventInfo::RequestData', //类名::
+ Explain: '大盘异动',
+ Request: { Url: url, Type: 'Get', Data: { Date: hqChart.TradeDate, Symbol: hqChart.Symbol } },
+ Self: this,
+ PreventDefault: false
+ };
+ hqChart.NetworkFilter(obj, function (data)
+ {
+ self.RecvData(data, param);
+ param.HQChart.UpdataChartInfo();
+ param.HQChart.Draw();
+ });
+
+ if (obj.PreventDefault == true) return; //已被上层替换,不调用默认的网络请求
+ }
+
+ //请求数据
+ wx.request({
+ url: url,
+ method: "get",
+ dataType: "json",
+ success: function (recvData) {
+ self.RecvData(recvData, param);
+ },
+ error: function (http, e) {
+ console.warn("[MarketEventInfo::RequestData] error, http ", e, http);
+ }
+ });
+
+ return true;
+ }
+
+ this.RecvData = function (recvData, param)
+ {
+ var data=recvData.data;
+ for (var i in data.event)
+ {
+ var event = data.event[i];
+ for (var j in event.data)
+ {
+ var item = event.data[j];
+ if (item.length < 2) continue;
+ var info = { Date: event.date, Time: item[0], Title: item[1], Type: 0 };
+ this.Data.push(info);
+ }
+ }
+
+ param.HQChart.UpdataChartInfo();
+ param.HQChart.Draw();
+ }
+}
+
+//导出统一使用JSCommon命名空间名
+module.exports =
+{
+ JSCommonKLineInfo:
+ {
+ JSKLineInfoMap: JSKLineInfoMap,
+ KLINE_INFO_TYPE: KLINE_INFO_TYPE,
+ JSMinuteInfoMap: JSMinuteInfoMap,
+ },
+
+ //单个类导出
+ JSCommon_JSKLineInfoMap: JSKLineInfoMap,
+ JSCommon_KLINE_INFO_TYPE: KLINE_INFO_TYPE,
+ JSCommon_JSMinuteInfoMap: JSMinuteInfoMap,
+};
\ No newline at end of file
diff --git a/uni_modules/jones-hqchart2/js_sdk/umychart.regressiontest.wechat.js b/uni_modules/jones-hqchart2/js_sdk/umychart.regressiontest.wechat.js
new file mode 100644
index 0000000..0c45f0e
--- /dev/null
+++ b/uni_modules/jones-hqchart2/js_sdk/umychart.regressiontest.wechat.js
@@ -0,0 +1,410 @@
+/*
+ Copyright (c) 2018 jones
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ 开源项目 https://github.com/jones2000/HQChart
+
+ jones_2000@163.com
+
+ 个股指标回测
+*/
+
+
+/*
+ 指标回测
+ 计算: Trade: {Count 交易次数 Days:交易天数 Success:成功交易次数 Fail:失败交易次数}
+ Day: {Count:总运行 Max:最长运行 Min:最短运行 Average:平均运行}
+ Profit: 总收益 StockProfit:个股收益 Excess:超额收益 MaxDropdown:最大回撤 Beta:β(Beta)系数(指标里面需要又大盘数据)
+ NetValue: [ {Date:日期, Net:净值, Close:股票收盘价, IndexClose:大盘的收盘价}, ]
+*/
+
+
+function RegressionTest()
+{
+ //只读数据不能修改
+ this.HistoryData; //K线数据
+ this.BuyData; //策略买数据
+ this.SellData; //策略卖数据
+ this.IndexClose; //大盘收盘价
+ this.NetCalculateModel=0; //净值及收益计算模型 0=使用B点开盘价计算 1=使用B点下一天的开盘价计算
+
+ this.InitialCapital=10000; //初始资金1W
+
+ //计算结果数据
+ this.Data=new Map(); //key:DATA_NAME value:数据
+
+ this.SetPolicyData=function(obj) //设置策略结果的数据 {KLineData:个股K线数据, BuyData:策略买数据, SellData:策略卖数据, IndexClose:大盘收盘价}
+ {
+ this.HistoryData=obj.KLineData; //K线数据
+ this.BuyData=obj.BuyData; //策略买数据
+ this.SellData=obj.SellData; //策略卖数据
+ if (obj.IndexClose) this.IndexClose=obj.IndexClose; //大盘收盘价 如果没有大盘数据 就不计算β(Beta)系数 和指数涨幅数据
+ }
+
+ this.ClearData=function() //清空所有的结果数据
+ {
+ this.Data=new Map()
+ }
+
+ this.GetBSData=function(startDate) //BS点配对 { B:[{Data:K线数据, Count:天数, NextOpen:下一天的开盘价 }], S:{Data:K线数据}}
+ {
+ var index=null;
+ for(var i=0;i=startDate)
+ {
+ index=i;
+ break;
+ }
+ }
+ if (index===null) return null;
+
+ console.log(`[RegressionTest::GetBSData] startDate=${startDate} index=${index}`);
+ var aryBS=[];
+ var bsItem=null;
+ for(var i=index;i0)
+ {
+ var bItem={Data:kLineItem, Count:0 };
+ if (i+10)
+ {
+ var bItem={Data:kLineItem, Count:0};
+ if (i+10)
+ {
+ bsItem.S={Data:kLineItem};
+ aryBS.push(bsItem);
+ bsItem=null;
+ }
+ }
+ }
+
+ var data={StartDate:this.HistoryData[index].Date, StartIndex:index, Count:this.HistoryData.length-index, BSData:aryBS };
+
+ console.log('[RegressionTest::GetBSData] data',data);
+ return data;
+ }
+
+ this.Calculate=function(data)
+ {
+ var day={ Count:data.Count, Max:null, Min:null, Average:null }; //Count:总运行 Max:最长运行 Min:最短运行 Average:平均运行
+ var trade={Count:0, Days:0, Success:0 , Fail:0, SuccessRate:0}; //Count 交易次数 Days:交易天数 Success:成功交易次数 Fail:失败交易次数
+
+ for(var i in data.BSData)
+ {
+ var item=data.BSData[i];
+ for(var j in item.B)
+ {
+ var bItem=item.B[j];
+ if (day.Max===null) day.Max=bItem.Count;
+ else if (day.MaxbItem.Count) day.Min=bItem.Count;
+
+ ++trade.Count;
+ trade.Days+=bItem.Count;
+
+ if (item.S.Data.Close>bItem.Data.Open) ++trade.Success;
+ else ++trade.Fail;
+ }
+ }
+
+ if (trade.Count>0)
+ {
+ day.Average=trade.Days/trade.Count;
+ trade.SuccessRate=trade.Success/trade.Count;
+ }
+
+ //计算收益(总收益)
+ var profit=1,buyPrice;
+ for(var i in data.BSData)
+ {
+ var item=data.BSData[i];
+ if (this.NetCalculateModel===1 && item.B[0].NextOpen>0 ) buyPrice=item.B[0].NextOpen;
+ else buyPrice=item.B[0].Data.Open;
+ var sellPrice=item.S.Data.Close;
+ var value=(sellPrice-buyPrice)/buyPrice+1;
+ profit*=value;
+ }
+ profit-=1; //公式:[(1+收益1)*(1+收益2)*(1+收益3)……(1+收益n)-1] x 100%
+
+ //标的证券收益
+ var yClose=this.HistoryData[data.StartIndex].Close; //使用前收盘
+ var close=this.HistoryData[this.HistoryData.length-1].Close; //最后一个大盘收盘价
+ var stockProfit=(close-yClose)/yClose;
+
+ console.log(`[RegressionTest::Calculate] stock profit first[${this.HistoryData[data.StartIndex].Date}, YClose=${this.HistoryData[data.StartIndex].YClose}] end[${this.HistoryData[this.HistoryData.length-1].Date}, Close=${this.HistoryData[this.HistoryData.length-1].Close}]`);
+
+ var netValue=this.CaclulateNetValue(data);
+ var maxDropdown=null, beta=null;
+ if (netValue && netValue.length>0)
+ {
+ maxDropdown=this.CaclulateMaxDropdown(netValue);
+ if (this.IndexClose) beta=this.CaclulateBeta(netValue);
+ }
+
+ //Profit:收益 StockProfit:标的证券收益 Excess:超额收益(加上BS配对的数据)
+ var result={ Day:day, Trade:trade, Profit:profit, StockProfit:stockProfit, Excess:profit-stockProfit, NetValue:netValue, MaxDropdown:maxDropdown, Beta:beta,BSDataPair:data.BSData};
+
+ console.log('[RegressionTest::Calculate] NetCalculateModel, result ',this.NetCalculateModel, result);
+ return result;
+ }
+
+ this.CaclulateNetValue=function(data) //计算净值
+ {
+ var index=data.StartIndex;
+
+ var aryDay=[]; //{Close:收盘 , Open:开盘, Position:持仓数量, Cache:现金 , MarketValue:总市值}
+ var lastDayItem={Position:0, Cache:this.InitialCapital };
+ var bsItem=null, buyPrice;
+ for(var i=index;i0) //买
+ {
+ bsItem={ B:{Data:kLineItem}, S:null};
+ if (this.NetCalculateModel===1 && i+10)
+ buyPrice=this.HistoryData[i+1].Open; //使用B点下一天的开盘价买
+ else
+ buyPrice=dayItem.Open;
+
+ let position=parseInt(dayItem.Cache/buyPrice); //开盘价买
+ let cache=dayItem.Cache-buyPrice*position; //剩余的现金
+
+ dayItem.Position=position;
+ dayItem.Cache=cache;
+ dayItem.MarketValue=dayItem.Position*dayItem.Close+dayItem.Cache; //市值 股票+现金
+ }
+ }
+ else
+ {
+ if (sellItem>0) //卖
+ {
+ bsItem.S={Data:kLineItem};
+ bsItem=null;
+
+ let stockValue=dayItem.Position*dayItem.Close; //卖掉的股票钱
+ dayItem.Position=0;
+ dayItem.Cache+=stockValue; //卖掉的钱放到现金里面
+ dayItem.MarketValue=dayItem.Position*dayItem.Close+dayItem.Cache; //市值 股票+现金
+ }
+ }
+
+ //缓存上一天的数据
+ lastDayItem.Position=dayItem.Position;
+ lastDayItem.Cache=dayItem.Cache;
+
+ dayItem.Net=dayItem.MarketValue/this.InitialCapital; //净值
+ if (this.IndexClose) dayItem.IndexClose=this.IndexClose[i]; //指数收盘价
+ aryDay.push(dayItem);
+ }
+
+ //console.log('[RegressionTest::CaclulateNetValue] aryDay',aryDay);
+ if (aryDay.length<=0) return [];
+
+ var netValue=[]; //净值 {Date:日期, Net:净值, Close:股票收盘价, IndexClose:大盘的收盘价}
+ for(var i=0;i0 && lastItem.IndexClose>0) indexProfit[i-1]=(item.IndexClose-lastItem.IndexClose)/lastItem.IndexClose;
+ if (item.Net>0 && lastItem.Net>0) bsProfit[i-1]=(item.Net-lastItem.Net)/lastItem.Net;
+ //if (item.Close>0 && lastItem.Close>0) bsProfit[i-1]=(item.Close-lastItem.Close)/lastItem.Close;
+
+ indexProfitTotal+=indexProfit[i-1];
+ bsProfitTotal+=bsProfit[i-1];
+
+ lastItem=item;
+ }
+
+ var averageIndexProfit=indexProfitTotal/indexProfit.length;
+ var averageBSProfit=bsProfitTotal/bsProfit.length;
+
+ var betaCOV=0; //协方差
+ for(var i=0;i DRAWICON
+ this.DRAWICON=
+ {
+ Text:
+ {
+ MaxSize:50, //字体最大
+ MinSize:20, //字体最小
+
+ Zoom:
+ {
+ Type:2, //0=放大(K线宽度*Value) 1=放大(K线+间距)*Value 2=(K线+间距)+2*Value;
+ Value:1
+ },
+
+ FontName:'Arial' //字体
+ }
+ }
+
+ this.DRAWTEXT=
+ {
+ MaxSize:18, //字体最大
+ MinSize:18, //字体最小
+
+ Zoom:
+ {
+ Type:1, //0=放大(K线宽度*Value) 1=放大(K线+间距)*Value 2=(K线+间距)+2*Value;
+ Value:1
+ },
+
+ FontName:'微软雅黑' //字体
+ }
+
+ this.DRAWNUMBER=
+ {
+ MaxSize:18, //字体最大
+ MinSize:18, //字体最小
+
+ Zoom:
+ {
+ Type:1, //0=放大(K线宽度*Value) 1=放大(K线+间距)*Value 2=(K线+间距)+2*Value;
+ Value:1
+ },
+
+ FontName:'微软雅黑' //字体
+ }
+
+ this.DRAWABOVE=
+ {
+ YOffset:0 //y坐标向上偏移
+ }
+
+ this.CIRCLEDOT=
+ {
+ Radius:1.3
+ }
+
+ this.POINTDOT=
+ {
+ Radius:2
+ }
+
+ //深度图
+ this.DepthChart=
+ {
+ BidColor: { Line:"rgb(82,176,123)", Area:"rgba(82,176,123,0.8)"}, //卖
+ AskColor: { Line:"rgb(207,76,89)", Area:"rgba(207,76,89, 0.8)"}, //买
+ LineWidth:4
+ }
+
+ this.DepthCorss=
+ {
+ BidColor: { Line:"rgb(82,176,123)" }, //卖
+ AskColor: { Line:"rgb(207,76,89)" }, //买
+ LineWidth:2, //线段宽度
+ LineDash:[3,3],
+ Tooltip:
+ {
+ BGColor:'rgba(236,240,245, 0.8)', TextColor:"rgb(130,140,151)",
+ Border:{ Top:5, Left:20, Bottom:5, Center: 5},
+ Font:"14px 微软雅黑",
+ LineHeight:16 //单行高度
+ }
+ }
+
+ // //自定义风格
+ this.SetStyle = function (style)
+ {
+ if (style.TooltipBGColor) this.TooltipBGColor = style.TooltipBGColor;
+ if (style.TooltipAlpha) this.TooltipAlpha = style.TooltipAlpha;
+ if (style.BGColor) this.BGColor = style.BGColor;
+ if (style.SelectRectBGColor) this.SelectRectBGColor = style.SelectRectBGColor;
+ if (style.UpBarColor) this.UpBarColor = style.UpBarColor;
+ if (style.DownBarColor) this.DownBarColor = style.DownBarColor;
+ if (style.UnchagneBarColor) this.UnchagneBarColor = style.UnchagneBarColor;
+ if (style.Minute)
+ {
+ if (style.Minute.VolBarColor) this.Minute.VolBarColor = style.Minute.VolBarColor;
+ if (style.Minute.PriceColor) this.Minute.PriceColor = style.Minute.PriceColor;
+ if (style.Minute.AvPriceColor) this.Minute.AvPriceColor = style.Minute.AvPriceColor;
+ if (style.Minute.AreaPriceColor) this.Minute.AreaPriceColor = style.Minute.AreaPriceColor;
+ }
+ if (style.DefaultTextColor) this.DefaultTextColor = style.DefaultTextColor;
+ if (style.DefaultTextFont) this.DefaultTextFont = style.DefaultTextFont;
+ if (style.DynamicTitleFont) this.DynamicTitleFont = style.DynamicTitleFont;
+ if (style.IndexTitleBGColor) this.IndexTitleBGColor=style.IndexTitleBGColor;
+ if (style.UpTextColor) this.UpTextColor = style.UpTextColor;
+ if (style.DownTextColor) this.DownTextColor = style.DownTextColor;
+ if (style.UnchagneTextColor) this.UnchagneTextColor = style.UnchagneTextColor;
+ if (style.CloseLineColor) this.CloseLineColor = style.CloseLineColor;
+ if (style.CloseLineAreaColor) this.CloseLineAreaColor = style.CloseLineAreaColor;
+ if (style.FrameBorderPen) this.FrameBorderPen = style.FrameBorderPen;
+ if (style.FrameSplitPen) this.FrameSplitPen = style.FrameSplitPen;
+ if (style.FrameSplitTextColor) this.FrameSplitTextColor = style.FrameSplitTextColor;
+ if (style.FrameSplitTextFont) this.FrameSplitTextFont = style.FrameSplitTextFont;
+ if (style.FrameTitleBGColor) this.FrameTitleBGColor = style.FrameTitleBGColor;
+
+ if (style.Frame)
+ {
+ if (style.Frame.XBottomOffset) this.Frame.XBottomOffset = style.Frame.XBottomOffset;
+ if (style.Frame.YTopOffset) this.Frame.YTopOffset = style.Frame.YTopOffset;
+ }
+
+ if (style.FrameLatestPrice)
+ {
+ if (style.FrameLatestPrice.TextColor) this.FrameLatestPrice.TextColor = style.FrameLatestPrice.TextColor;
+ if (style.FrameLatestPrice.UpBarColor) this.FrameLatestPrice.UpBarColor = style.FrameLatestPrice.UpBarColor;
+ if (style.FrameLatestPrice.DownBarColor) this.FrameLatestPrice.DownBarColor = style.FrameLatestPrice.DownBarColor;
+ if (style.FrameLatestPrice.UnchagneBarColor) this.FrameLatestPrice.UnchagneBarColor = style.FrameLatestPrice.UnchagneBarColor;
+ if (style.FrameLatestPrice.BGAlpha) this.FrameLatestPrice.BGAlpha = style.FrameLatestPrice.BGAlpha;
+ }
+
+ if (style.CorssCursorBGColor) this.CorssCursorBGColor = style.CorssCursorBGColor;
+ if (style.CorssCursorTextColor) this.CorssCursorTextColor = style.CorssCursorTextColor;
+ if (style.CorssCursorTextFont) this.CorssCursorTextFont = style.CorssCursorTextFont;
+ if (style.CorssCursorHPenColor) this.CorssCursorHPenColor = style.CorssCursorHPenColor;
+ if (style.CorssCursorVPenColor) this.CorssCursorVPenColor = style.CorssCursorVPenColor;
+ if (style.KLine) this.KLine = style.KLine;
+ if (style.Index)
+ {
+ if (style.Index.LineColor) this.Index.LineColor = style.Index.LineColor;
+ if (style.Index.NotSupport) this.Index.NotSupport = style.Index.NotSupport;
+ }
+
+ if (style.ColorArray) this.ColorArray = style.ColorArray;
+
+ if (style.DrawPicture)
+ {
+ this.DrawPicture.LineColor = style.DrawPicture.LineColor;
+ this.DrawPicture.PointColor = style.DrawPicture.PointColor;
+ }
+
+ if (style.TooltipPaint)
+ {
+ if (style.TooltipPaint.BGColor) this.TooltipPaint.BGColor = style.TooltipPaint.BGColor;
+ if (style.TooltipPaint.BorderColor) this.TooltipPaint.BorderColor = style.TooltipPaint.BorderColor;
+ if (style.TooltipPaint.TitleColor) this.TooltipPaint.TitleColor = style.TooltipPaint.TitleColor;
+ if (style.TooltipPaint.TitleFont) this.TooltipPaint.TitleFont = style.TooltipPaint.TitleFont;
+ }
+
+ if (style.Title)
+ {
+ if (style.Title.TradeIndexColor) this.Title.TradeIndexColor=style.Title.TradeIndexColor;
+ if (style.Title.ColorIndexColor) this.Title.ColorIndexColor=style.Title.ColorIndexColor;
+
+ if (style.Title.VolColor) this.Title.VolColor=style.Title.VolColor;
+ if (style.Title.AmountColor) this.Title.AmountColor=style.Title.AmountColor;
+ if (style.Title.DateTimeColor) this.Title.DateTimeColor=style.Title.DateTimeColor;
+ if (style.Title.NameColor) this.Title.NameColor=style.Title.NameColor;
+ if (style.Title.SettingColor) this.Title.SettingColor=style.Title.SettingColor;
+ if (style.Title.TurnoverRateColor) this.Title.TurnoverRateColor=style.Title.TurnoverRateColor;
+ if (style.Title.PositionColor) this.Title.PositionColor=style.Title.PositionColor;
+ }
+
+ if (style.DRAWICON)
+ {
+ if (style.DRAWICON.Text)
+ {
+ var item=style.DRAWICON.Text;
+ if (IFrameSplitOperator.IsPlusNumber(item.MaxSize)) this.DRAWICON.Text.MaxSize=item.MaxSize;
+ if (IFrameSplitOperator.IsPlusNumber(item.MinSize)) this.DRAWICON.Text.MinSize=item.MinSize;
+ if (item.Zoom) this.DRAWICON.Text.Zoom=item.Zoom;
+ if (item.FontName) this.DRAWICON.Text.FontName=item.FontName;
+ }
+ }
+
+ if (style.DRAWTEXT)
+ {
+ var item=style.DRAWTEXT;
+ if (IFrameSplitOperator.IsPlusNumber(item.MaxSize)) this.DRAWICON.MaxSize=item.MaxSize;
+ if (IFrameSplitOperator.IsPlusNumber(item.MinSize)) this.DRAWICON.MinSize=item.MinSize;
+ if (item.Zoom) this.DRAWICON.Zoom=item.Zoom;
+ if (item.FontName) this.DRAWICON.FontName=item.FontName;
+ }
+
+ if (style.DRAWNUMBER)
+ {
+ var item=style.DRAWNUMBER;
+ if (this.IsPlusNumber(item.MaxSize)) this.DRAWNUMBER.Text.MaxSize=item.MaxSize;
+ if (this.IsPlusNumber(item.MinSize)) this.DRAWNUMBER.Text.MinSize=item.MinSize;
+ if (item.Zoom) this.DRAWNUMBER.Text.Zoom=item.Zoom;
+ if (item.FontName) this.DRAWNUMBER.Text.FontName=item.FontName;
+ }
+
+ if (style.DRAWABOVE)
+ {
+ var item=style.DRAWABOVE;
+ if (this.IsNumber(item.YOffset)) this.DRAWABOVE.YOffset=item.YOffset;
+ }
+
+ if (style.DepthChart)
+ {
+ var item=style.DepthChart;
+ if (item.BidColor)
+ {
+ if (item.BidColor.Line) this.DepthChart.BidColor.Line=item.BidColor.Line;
+ if (item.BidColor.Area) this.DepthChart.BidColor.Area=item.BidColor.Area;
+ }
+ if (item.AskColor)
+ {
+ if (item.AskColor.Line) this.DepthChart.AskColor.Line=item.AskColor.Line;
+ if (item.AskColor.Area) this.DepthChart.AskColor.Area=item.AskColor.Area;
+ }
+
+ if (item.LineWidth) this.DepthChart.LineWidth=item.LineWidth;
+ }
+
+ if (style.DepthCorss)
+ {
+ var item=style.DepthCorss;
+ if (item.BidColor)
+ {
+ if (item.BidColor.Line) this.DepthCorss.BidColor.Line=item.BidColor.Line;
+ }
+
+ if (item.AskColor)
+ {
+ if (item.AskColor.Line) this.DepthCorss.AskColor.Line=item.AskColor.Line;
+ }
+
+ if (item.LineWidth) this.DepthCorss.LineWidth=item.LineWidth;
+ if (item.LineDash) this.DepthCorss.LineDash=item.LineDash;
+
+ if (item.Tooltip)
+ {
+ var tooltip=item.Tooltip;
+ if (tooltip.BGColor) this.DepthCorss.Tooltip.BGColor=tooltip.BGColor;
+ if (tooltip.TextColor) this.DepthCorss.Tooltip.TextColor=tooltip.TextColor;
+ if (tooltip.Font) this.DepthCorss.Tooltip.Font=tooltip.Font;
+ if (tooltip.LineHeight) this.DepthCorss.Tooltip.LineHeight=tooltip.LineHeight;
+
+ var border=tooltip.Border;
+ if (this.IsNumber(border.Top)) this.DepthCorss.Tooltip.Border.Top=border.Top;
+ if (this.IsNumber(border.Left)) this.DepthCorss.Tooltip.Border.Left=border.Left;
+ if (this.IsNumber(border.Bottom)) this.DepthCorss.Tooltip.Border.Bottom=border.Bottom;
+ if (this.IsNumber(border.Center)) this.DepthCorss.Tooltip.Border.Center=border.Center;
+ }
+ }
+
+ if (style.CIRCLEDOT)
+ {
+ var item=style.CIRCLEDOT;
+ if (this.IsNumber(item.Radius)) this.CIRCLEDOT.Radius=item.Radius;
+ }
+
+ if (style.POINTDOT)
+ {
+ var item=style.POINTDOT;
+ if (this.IsNumber(item.Radius)) this.POINTDOT.Radius=item.Radius;
+ }
+ }
+
+
+ this.IsNumber=function(value)
+ {
+ if (value==null) return false;
+ if (isNaN(value)) return false;
+
+ return true;
+ }
+
+ //判断是否是正数
+ this.IsPlusNumber=function(value)
+ {
+ if (value==null) return false;
+ if (isNaN(value)) return false;
+
+ return value>0;
+ }
+}
+
+var g_JSChartResource = new JSChartResource();
+
+var JSCHART_LANGUAGE_ID =
+{
+ LANGUAGE_CHINESE_ID: 0,
+ LANGUAGE_ENGLISH_ID: 1
+};
+
+function JSChartLocalization()
+{
+ this.TextResource = new Map([
+ //内部tooltip
+ ['Tooltip-Open', { CN: '开:', EN: 'O:' }],
+ ['Tooltip-High', { CN: '高:', EN: 'H:' }],
+ ['Tooltip-Low', { CN: '低:', EN: 'L:' }],
+ ['Tooltip-Close', { CN: '收:', EN: 'C:' }],
+ ['Tooltip-Increase', { CN: '幅:', EN: 'I:' }],
+ ['Tooltip-Vol', { CN: '量:', EN: 'V:' }],
+ ['Tooltip-Amount', { CN: '额:', EN: 'A:' }],
+ ['Tooltip-AvPrice', { CN: '均:', EN: 'AP:' }],
+ ['Tooltip-Price', { CN: '价:', EN: 'P:' }],
+ ['Tooltip-Exchange', { CN: '换:', EN: 'E:' }],
+ ['Tooltip-Position', { CN: '持:', EN: 'P:' }],
+
+ //K线动态标题
+ ['KTitle-Open', { CN: '开:', EN: 'O:' }],
+ ['KTitle-High', { CN: '高:', EN: 'H:' }],
+ ['KTitle-Low', { CN: '低:', EN: 'L:' }],
+ ['KTitle-Close', { CN: '收:', EN: 'C:' }],
+ ['KTitle-Increase', { CN: '幅:', EN: 'I:' }],
+ ['KTitle-Vol', { CN: '量:', EN: 'V:' }],
+ ['KTitle-Amount', { CN: '额:', EN: 'A:' }],
+ ['KTitle-Exchange', { CN: '换:', EN: 'E:' }],
+ ['KTitle-Position', { CN: '持:', EN: 'P:' }],
+
+ //走势图动态标题
+ ['MTitle-Close', { CN: '价:', EN: 'C:' }],
+ ['MTitle-AvPrice', { CN: '均:', EN: 'AC:' }],
+ ['MTitle-Increase', { CN: '幅:', EN: 'I:' }],
+ ['MTitle-Vol', { CN: '量:', EN: 'V:' }],
+ ['MTitle-Amount', { CN: '额:', EN: 'A:' }],
+ ['MTitle-Position', { CN: '持:', EN: 'P:' }],
+
+ //周期
+ ['日线', { CN: '日线', EN: '1D' }],
+ ['周线', { CN: '周线', EN: '1W' }],
+ ['双周', { CN: '双周', EN: "2W" }],
+ ['月线', { CN: '月线', EN: '1M' }],
+ ['年线', { CN: '年线', EN: '1Y' }],
+ ['1分', { CN: '1分', EN: '1Min' }],
+ ['5分', { CN: '5分', EN: '5Min' }],
+ ['15分', { CN: '15分', EN: '15Min' }],
+ ['30分', { CN: '30分', EN: '30Min' }],
+ ['60分', { CN: '60分', EN: '60Min' }],
+ ['季线', { CN: '季线', EN: '1Q' }],
+ ['分笔', { CN: '分笔', EN: 'Tick' }],
+ ['2小时', { CN: '2小时', EN: '2H' }],
+ ['4小时', { CN: '4小时', EN: '4H' }],
+
+ //复权
+ ['不复权', { CN: '不复权', EN: 'No Right' }],
+ ['前复权', { CN: '前复权', EN: 'Pro Right' }],
+ ['后复权', { CN: '后复权', EN: 'Post Right' }],
+
+ //week
+ ['日', { CN: '日', EN: 'Sun.' }],
+ ['一', { CN: '一', EN: 'Mon.' }],
+ ['二', { CN: '二', EN: 'Tues.' }],
+ ['三', { CN: '三', EN: 'Wed.' }],
+ ['四', { CN: '四', EN: 'Thur.' }],
+ ['五', { CN: '五', EN: 'Fri.' }],
+ ['六', { CN: '六', EN: 'Sat.' }],
+
+ ['1月', { CN: '1月', EN: 'Jan' }],
+ ['2月', { CN: '2月', EN: 'Feb' }],
+ ['3月', { CN: '3月', EN: 'Mar' }],
+ ['4月', { CN: '4月', EN: 'Apr' }],
+ ['5月', { CN: '5月', EN: 'May' }],
+ ['6月', { CN: '6月', EN: 'Jun' }],
+ ['7月', { CN: '7月', EN: 'Jul' }],
+ ['8月', { CN: '8月', EN: 'Aug' }],
+ ['9月', { CN: '9月', EN: 'Sept' }],
+ ['10月', { CN: '10月', EN: 'Oct' }],
+ ['11月', { CN: '11月', EN: 'Nov' }],
+ ['12月', { CN: '12月', EN: 'Dec' }],
+
+ ['自定义分钟', { CN: '分', EN: 'Min' }],
+ ['自定义日线', { CN: '日', EN: 'D' }],
+ ['自定义秒', { CN: '秒', EN: 'S' }]
+
+ ]);
+
+ this.GetText = function (key, language)
+ {
+ var item = this.TextResource.get(key);
+ if (!item) return '';
+
+ switch (language)
+ {
+ case JSCHART_LANGUAGE_ID.LANGUAGE_CHINESE_ID:
+ return item.CN;
+ case JSCHART_LANGUAGE_ID.LANGUAGE_ENGLISH_ID:
+ return item.EN;
+ default:
+ return item.CN;
+ }
+ }
+
+ this.SetTextResource = function (key, value)
+ {
+ this.TextResource.set(key, value)
+ }
+};
+
+var g_JSChartLocalization = new JSChartLocalization();
+
+//导出统一使用JSCommon命名空间名
+module.exports =
+{
+ JSCommonResource:
+ {
+ JSChartResource: JSChartResource,
+ Global_JSChartResource: g_JSChartResource,
+ Global_JSChartLocalization: g_JSChartLocalization,
+ JSCHART_LANGUAGE_ID: JSCHART_LANGUAGE_ID,
+ },
+
+ //单个类导出
+ JSCommonResource_JSChartResource: JSChartResource,
+ JSCommonResource_Global_JSChartResource: g_JSChartResource,
+ JSCommonResource_Global_JSChartLocalization: g_JSChartLocalization,
+ JSCommonResource_JSCHART_LANGUAGE_ID: JSCHART_LANGUAGE_ID
+};
\ No newline at end of file
diff --git a/uni_modules/jones-hqchart2/js_sdk/umychart.style.wechat.js b/uni_modules/jones-hqchart2/js_sdk/umychart.style.wechat.js
new file mode 100644
index 0000000..002c04c
--- /dev/null
+++ b/uni_modules/jones-hqchart2/js_sdk/umychart.style.wechat.js
@@ -0,0 +1,342 @@
+/*
+ copyright (c) 2018 jones
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ 开源项目 https://github.com/jones2000/HQChart
+
+ jones_2000@163.com
+
+ 不同风格行情配置文件 (微信小程序版本)
+*/
+
+var BLACK_STYLE = //黑色风格
+{
+ BGColor:'rgb(0,0,0)',
+ TooltipBGColor: "rgb(255, 255, 255)", //背景色
+ TooltipAlpha: 0.92, //透明度
+
+ SelectRectBGColor: "rgba(1,130,212,0.06)", //背景色
+ // SelectRectAlpha: 0.06; //透明度
+
+ UpBarColor: "rgb(238,21,21)",
+ DownBarColor: "rgb(25,158,0)",
+ UnchagneBarColor: "rgb(199,199,199)",
+
+ Minute: {
+ VolBarColor: null,
+ PriceColor: "rgb(25,180,231)",
+ AvPriceColor: "rgb(255,236,0)",
+ },
+
+
+ DefaultTextColor: "rgb(101,104,112)",
+ DefaultTextFont: '14px 微软雅黑',
+ IndexTitleBGColor:'rgb(211,211,211)',
+
+ DynamicTitleFont: '12px 微软雅黑', //指标动态标题字体
+
+
+ UpTextColor: "rgb(238,21,21)",
+ DownTextColor: "rgb(25,158,0)",
+ UnchagneTextColor: "rgb(101,104,112)",
+ CloseLineColor: 'rgb(178,34,34)',
+
+ Title:
+ {
+ TradeIndexColor:'rgb(105,105,105)', //交易指标颜色
+ ColorIndexColor:'rgb(112,128,144)', //五彩K线颜色
+
+ VolColor:"rgb(101,104,112)", //标题成交量
+ AmountColor:"rgb(101,104,112)", //成交金额
+ DateTimeColor:"rgb(101,104,112)", //时间,日期
+ SettingColor:"rgb(101,104,112)", //周期,复权
+ NameColor:"rgb(101,104,112)" , //股票名称
+ TurnoverRateColor:'rgb(101,104,112)', //换手率
+ PositionColor:"rgb(101,104,112)" //持仓
+ },
+
+ FrameBorderPen: "rgba(236,236,236,0.13)", //边框
+ FrameSplitPen: "rgba(236,236,236,0.13)", //分割线
+ FrameSplitTextColor: "rgb(101,104,112)", //刻度文字颜色
+ FrameSplitTextFont: "12px 微软雅黑", //坐标刻度文字字体
+ FrameTitleBGColor: "rgb(246,251,253)", //标题栏背景色
+ Frame: { XBottomOffset: 0 }, //X轴文字向下偏移
+
+ FrameLatestPrice: {
+ TextColor: 'rgb(255,255,255)', //最新价格文字颜色
+ UpBarColor: "rgb(238,21,21)", //上涨
+ DownBarColor: "rgb(25,158,0)", //下跌
+ UnchagneBarColor: "rgb(190,190,190)", //平盘
+ BGAlpha: 0.6
+ },
+
+ CorssCursorBGColor: "rgb(43,54,69)", //十字光标背景
+ CorssCursorTextColor: "rgb(255,255,255)",
+ CorssCursorTextFont: "12px 微软雅黑",
+ CorssCursorHPenColor: "rgb(130,130,130)", //十字光标线段颜色
+ CorssCursorVPenColor: "rgb(130,130,130)", //十字光标线段颜色
+
+ KLine:
+ {
+ MaxMin: { Font: '12px 微软雅黑', Color: 'rgb(111,111,111)', RightArrow:"→", LeftArrow:"←", HighYOffset:0, LowYOffset:0 }, //K线最大最小值显示
+ Info: //信息地雷
+ {
+ Color: 'rgb(205,149,12)',
+ TextColor: '#afc0da',
+ TextBGColor: '#1a283e',
+ Investor:
+ {
+ ApiUrl: '/API/NewsInteract', //互动易
+ },
+ Announcement: //公告
+ {
+ ApiUrl: '/API/ReportList',
+ },
+ Pforecast: //业绩预告
+ {
+ ApiUrl: '/API/StockHistoryDay',
+ },
+ Research: //调研
+ {
+ ApiUrl: '/API/InvestorRelationsList',
+ },
+ BlockTrading: //大宗交易
+ {
+ ApiUrl: '/API/StockHistoryDay',
+ },
+ TradeDetail: //龙虎榜
+ {
+ ApiUrl: '/API/StockHistoryDay',
+ },
+ Policy: //策略
+ {
+ ApiUrl: '/API/StockHistoryDay',
+ }
+ }
+ },
+
+ Index: { //指标线段颜色
+ LineColor: [
+ "rgb(255,189,09)",
+ "rgb(22,198,255)",
+ "rgb(174,35,161)",
+ "rgb(236,105,65)",
+ "rgb(68,114,196)",
+ "rgb(229,0,79)",
+ "rgb(0,128,255)",
+ "rgb(252,96,154)",
+ "rgb(42,230,215)",
+ "rgb(24,71,178)",
+
+ ],
+ NotSupport: { Font: "14px 微软雅黑", TextColor: "rgb(52,52,52)" }
+ },
+
+ ColorArray: //自定义指标默认颜色
+ [
+ "rgb(255,174,0)",
+ "rgb(25,199,255)",
+ "rgb(175,95,162)",
+ "rgb(236,105,65)",
+ "rgb(68,114,196)",
+ "rgb(229,0,79)",
+ "rgb(0,128,255)",
+ "rgb(252,96,154)",
+ "rgb(42,230,215)",
+ "rgb(24,71,178)",
+ ],
+ //画图工具
+ DrawPicture:
+ {
+ LineColor: "rgb(30,144,255)",
+ PointColor: "rgb(105,105,105)",
+ },
+
+ TooltipPaint: //Tooltip
+ {
+ BGColor: 'rgba(20,20,20,0.8)', //背景色
+ BorderColor: 'rgb(210,210,210)', //边框颜色
+ TitleColor: 'rgb(210,210,210)', //标题颜色
+ TitleFont:'13px 微软雅黑' //字体
+ },
+
+ //深度图
+ DepthChart:
+ {
+ BidColor: { Line:"rgb(82,176,123)", Area:"rgba(82,176,123,0.5)"}, //卖
+ AskColor: { Line:"rgb(207,76,89)", Area:"rgba(207,76,89, 0.5)"}, //买
+ LineWidth:4
+ },
+
+ DepthCorss:
+ {
+ BidColor: { Line:"rgb(82,176,123)" }, //卖
+ AskColor: { Line:"rgb(207,76,89)" }, //买
+ LineWidth:2, //线段宽度
+ LineDash:[3,3],
+ Tooltip:
+ {
+ BGColor:'rgba(54,54,54, 0.8)', TextColor:"rgb(203,215,224)",
+ Border:{ Top:5, Left:20, Bottom:5, Center: 5},
+ Font:"14px 微软雅黑",
+ LineHeight:16 //单行高度
+ }
+ }
+};
+
+
+var WHITE_STYLE= //白色风格
+{
+ BGColor:'rgb(255,255,255)',
+ TooltipBGColor: "rgb(255, 255, 255)", //背景色
+ TooltipAlpha: 0.92, //透明度
+
+ SelectRectBGColor:"rgba(1,130,212,0.06)", //背景色
+ // this.SelectRectAlpha=0.06; //透明度
+
+ UpBarColor: "rgb(238,21,21)",
+ DownBarColor: "rgb(25,158,0)",
+ UnchagneBarColor: "rgb(0,0,0)",
+
+ Minute:
+ {
+ VolBarColor : "rgb(238,127,9)",
+ PriceColor : "rgb(50,171,205)",
+ AvPriceColor : "rgb(238,127,9)",
+ },
+
+ DefaultTextColor: "rgb(43,54,69)",
+ DefaultTextFont: '14px 微软雅黑',
+
+ DynamicTitleFont: '12px 微软雅黑', //指标动态标题字体
+
+
+ UpTextColor: "rgb(238,21,21)",
+ DownTextColor: "rgb(25,158,0)",
+ UnchagneTextColor: "rgb(0,0,0)",
+ CloseLineColor: 'rgb(178,34,34)',
+
+ FrameBorderPen: "rgb(225,236,242)", //边框
+ FrameSplitPen: "rgb(225,236,242)", //分割线
+ FrameSplitTextColor: "rgb(51,51,51)", //刻度文字颜色
+ FrameSplitTextFont: "12px 微软雅黑", //坐标刻度文字字体
+ FrameTitleBGColor: "rgb(246,251,253)", //标题栏背景色
+
+ CorssCursorBGColor: "rgb(43,54,69)", //十字光标背景
+ CorssCursorTextColor: "rgb(255,255,255)",
+ CorssCursorTextFont: "12px 微软雅黑",
+ CorssCursorPenColor: "rgb(130,130,130)", //十字光标线段颜色
+
+ KLine:
+ {
+ MaxMin: { Font: '12px 微软雅黑', Color: 'rgb(111,111,111)' }, //K线最大最小值显示
+ Info: //信息地雷
+ {
+ Color: 'rgb(205,149,12)',
+ TextColor: '#197de9',
+ TextBGColor: '#e1e4ef',
+ Investor:
+ {
+ ApiUrl: '/API/NewsInteract', //互动易
+ },
+ Announcement: //公告
+ {
+ ApiUrl: '/API/ReportList',
+ },
+ Pforecast: //业绩预告
+ {
+ ApiUrl: '/API/StockHistoryDay',
+ },
+ Research: //调研
+ {
+ ApiUrl: '/API/InvestorRelationsList',
+ },
+ BlockTrading: //大宗交易
+ {
+ ApiUrl: '/API/StockHistoryDay',
+ },
+ TradeDetail: //龙虎榜
+ {
+ ApiUrl: '/API/StockHistoryDay',
+ },
+ Policy: //策略
+ {
+ ApiUrl: '/API/StockHistoryDay',
+ }
+ }
+ },
+
+ Index:
+ { //指标线段颜色
+ LineColor:
+ [
+ "rgb(255,189,09)",
+ "rgb(22,198,255)",
+ "rgb(174,35,161)",
+ "rgb(236,105,65)",
+ "rgb(68,114,196)",
+ "rgb(229,0,79)",
+ "rgb(0,128,255)",
+ "rgb(252,96,154)",
+ "rgb(42,230,215)",
+ "rgb(24,71,178)",
+ ],
+ NotSupport: { Font: "14px 微软雅黑", TextColor: "rgb(52,52,52)" }
+ },
+
+ ColorArray: //自定义指标默认颜色
+ [
+ "rgb(255,174,0)",
+ "rgb(25,199,255)",
+ "rgb(175,95,162)",
+ "rgb(236,105,65)",
+ "rgb(68,114,196)",
+ "rgb(229,0,79)",
+ "rgb(0,128,255)",
+ "rgb(252,96,154)",
+ "rgb(42,230,215)",
+ "rgb(24,71,178)",
+ ],
+
+ //画图工具
+ DrawPicture:
+ {
+ LineColor: "rgb(30,144,255)",
+ PointColor: "rgb(105,105,105)",
+ },
+}
+
+var STYLE_TYPE_ID=
+{
+ BLACK_ID:1, //黑色风格
+ WHITE_ID:2 //白色风格
+}
+
+
+function GetStyleConfig(styleid) //获取一个风格的配置变量
+{
+ switch (styleid)
+ {
+ case STYLE_TYPE_ID.BLACK_ID:
+ return BLACK_STYLE;
+ break;
+ case STYLE_TYPE_ID.WHITE_ID:
+ return WHITE_STYLE;
+ break;
+ default:
+ return null;
+ }
+}
+
+
+module.exports =
+ {
+ JSCommonHQStyle:
+ {
+ GetStyleConfig:GetStyleConfig,
+ STYLE_TYPE_ID:STYLE_TYPE_ID
+ }
+ };
+
+
diff --git a/uni_modules/jones-hqchart2/js_sdk/umychart.uniapp.canvas.helper.js b/uni_modules/jones-hqchart2/js_sdk/umychart.uniapp.canvas.helper.js
new file mode 100644
index 0000000..5e26374
--- /dev/null
+++ b/uni_modules/jones-hqchart2/js_sdk/umychart.uniapp.canvas.helper.js
@@ -0,0 +1,71 @@
+/*
+copyright (c) 2018 jones
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ 开源项目 https://github.com/jones2000/HQChart
+
+ jones_2000@163.com
+
+ uniapp canvas 兼容方法
+*/
+
+function JSUniAppCanvasHelper() { }
+
+JSUniAppCanvasHelper.MeasureText=function(text, canvas)
+{
+ var font = canvas.font;
+ var fontSize = 12;
+ var pos=font.search('px');
+ if (pos>0)
+ {
+ var strSize = font.substring(0,pos);
+ fontSize = parseInt(strSize);
+ }
+ text = String(text);
+ var text = text.split('');
+ var width = 0;
+ for (let i = 0; i < text.length; i++)
+ {
+ let item = text[i];
+ if (/[a-zA-Z]/.test(item))
+ {
+ width += 7;
+ } else if (/[0-9]/.test(item))
+ {
+ width += 5.5;
+ } else if (/\./.test(item))
+ {
+ width += 2.7;
+ } else if (/-/.test(item))
+ {
+ width += 3.25;
+ } else if (/[\u4e00-\u9fa5]/.test(item))
+ {
+ width += 10;
+ } else if (/\(|\)/.test(item))
+ {
+ width += 3.73;
+ } else if (/\s/.test(item))
+ {
+ width += 2.5;
+ } else if (/%/.test(item))
+ {
+ width += 8;
+ } else
+ {
+ width += 10;
+ }
+ }
+ return width * fontSize / 10;
+}
+
+//导出统一使用JSCommon命名空间名
+module.exports =
+{
+ JSCommonUniApp:
+ {
+ JSUniAppCanvasHelper: JSUniAppCanvasHelper,
+ }
+};
+
diff --git a/uni_modules/jones-hqchart2/js_sdk/umychart.uniapp.h5.js b/uni_modules/jones-hqchart2/js_sdk/umychart.uniapp.h5.js
new file mode 100644
index 0000000..5b09e71
--- /dev/null
+++ b/uni_modules/jones-hqchart2/js_sdk/umychart.uniapp.h5.js
@@ -0,0 +1,84908 @@
+
+//日志输出类
+var JSConsole=
+{
+ Chart:{ Log:console.log }, //图形日志
+ Complier:{ Log:console.log }, //编译器日志
+ JSTable:{ Log:console.log } //表格日志
+};
+
+
+
+
+/*
+ Copyright (c) 2018 jones
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ 开源项目 https://github.com/jones2000/HQChart
+
+ jones_2000@163.com
+
+ 系统指标 (H5版本)
+*/
+
+
+/*
+ 指标数据脚本 系统内置指标都写在这里
+ Name:指标名字
+ Description:指标描述信息
+ Args:参数 { Name:名字, Value=值 }
+ IsMainIndex:是否是主图指标 true=主图指标 false=副图指标
+ KLineType:K线设置 -1=主图不显示K线(只在主图有效) 0=在副图显示K线 1=在副图显示K线(收盘价线) 2=在副图显示K线(美国线)
+ InstructionType: 1=专家指示 2=五彩K线
+ FloatPrecision: 小数位数 缺省=2
+ YSplitScale: Y固定刻度 [1,8,10]
+ YSpecificMaxMin: 固定Y轴最大最小值 { Max: 9, Min: 0, Count: 3 };
+ StringFormat: 1=带单位万/亿 2=原始格式
+ Condition: 限制条件 { Symbol:'Index'/'Stock'(只支持指数/股票),Period:[](支持的周期), Include:[](指定支持的股票,代码全部大写包括后缀)}
+ OutName:动态输出变量名字 [{Name:原始变量名, DynamicName:动态名字格式}] 如 {Name:"MA1", DynamicName:"MA{M1}"};
+*/
+
+//周期条件枚举
+var CONDITION_PERIOD=
+{
+ MINUTE_ID:101, //分钟 走势图
+ MULTIDAY_MINUTE_ID:102, //多日分钟 走势图
+ HISTORY_MINUTE_ID:103, //历史分钟 走势图
+
+ //K线周期
+ KLINE_DAY_ID:0,
+ KLINE_WEEK_ID:1,
+ KLINE_TWOWEEK_ID:21,
+ KLINE_MONTH_ID:2,
+ KLINE_QUARTER_ID:9,
+
+ KLINE_YEAR_ID:3,
+ KLINE_MINUTE_ID:4,
+ KLINE_5_MINUTE_ID:5,
+ KLINE_15_MINUTE_ID:6,
+ KLINE_30_MINUTE_ID:7,
+ KLINE_60_MINUTE_ID:8,
+};
+
+//自定义的指标脚本
+function CustomIndexScript()
+{
+ this.DataMap=new Map(); //key=指标id, value=data {ID:, Name:指标名字, Description:指标描述信息 Args:参数 ......}
+
+ this.Get=function(id)
+ {
+ if (!this.DataMap.has(id)) return null;
+ return this.DataMap.get(id);
+ }
+
+ this.Add=function(data)
+ {
+ this.DataMap.set(data.ID, data);
+ }
+}
+
+var g_CustomIndex=new CustomIndexScript();
+
+function JSIndexScript()
+{
+ this.DataMap=new Map(
+ [
+ ['MA', this.MA],['均线', this.MA],
+ ["MA4", this.MA4],["MA5", this.MA5],["MA6", this.MA6],["MA7", this.MA7],["MA8", this.MA8],
+ ['BOLL', this.BOLL],['BOLL副图', this.BOLL2],['BBI', this.BBI],
+ ['DKX', this.DKX],['MIKE', this.MIKE],['PBX', this.PBX],
+ ['ENE', this.ENE],['MACD', this.MACD],['KDJ', this.KDJ],["MACD2", this.MACD2],
+ ['VOL', this.VOL],['RSI', this.RSI],['BRAR', this.BRAR],
+ ['WR', this.WR],['BIAS', this.BIAS],['OBV', this.OBV],
+ ['DMI', this.DMI],['CR', this.CR],['PSY', this.PSY],
+ ['CCI', this.CCI],['DMA', this.DMA],['TRIX', this.TRIX],
+ ['VR', this.VR],['EMV', this.EMV],['ROC', this.ROC],
+ ['MTM', this.MTM],['FSL', this.FSL],['CYR', this.CYR],
+ ['MASS', this.MASS],['WAD', this.WAD],['CHO', this.CHO],
+ ['ADTM', this.ADTM],['HSL', this.HSL],['BIAS36', this.BIAS36],
+ ['BIAS_QL', this.BIAS_QL],['DPO', this.DPO],['OSC', this.OSC],
+ ['ATR', this.ATR],['NVI', this.NVI],['PVI', this.PVI],
+ ['UOS', this.UOS],['CYW', this.CYW],['LON', this.LON],
+ ['NDB', this.NDB],['SKDJ',this.SKDJ],['KD',this.KD],['FKX',this.FKX],
+ ['DKCOL',this.DKCOL],['UDL',this.UDL],['MFI',this.MFI],['LWR',this.LWR],
+ ['MARSI',this.MARSI],['CYD',this.CYD],['CYF',this.CYF],['TAPI',this.TAPI],
+ ['VMACD',this.VMACD],['QACD',this.QACD],['VPT',this.VPT],['WVAD',this.WVAD],
+ ['DBQR',this.DBQR],['JS',this.JS],['CYE',this.CYE],['QR',this.QR],['GDX',this.GDX],
+ ['JLHB',this.JLHB],['PCNT',this.PCNT],['BTX', this.BTX],['AMO',this.AMO],
+ ['VRSI',this.VRSI],['HSCOL',this.HSCOL],['DBQRV',this.DBQRV],['DBLB',this.DBLB],
+ ['ACD',this.ACD],['EXPMA',this.EXPMA],['EXPMA_S',this.EXPMA_S],['HMA',this.HMA],
+ ['LMA',this.LMA],['VMA',this.VMA],['AMV',this.AMV],['BBIBOLL',this.BBIBOLL],
+ ['ALLIGAT',this.ALLIGAT],['ZX',this.ZX],['XS',this.XS],['XS2',this.XS2],
+ ['SG-XDT',this.SG_XDT],['SG-SMX',this.SG_SMX],['SG-LB',this.SG_LB],['SG-PF',this.SG_PF],
+ ['RAD',this.RAD],['SHT',this.SHT],['ZLJC',this.ZLJC],['ZLMM',this.ZLMM],['SLZT',this.SLZT],
+ ['ADVOL',this.ADVOL],['CYC',this.CYC],['CYS',this.CYS],['CYQKL',this.CYQKL],
+ ['SCR',this.SCR],['ASR',this.ASR],['SAR',this.SAR],['TJCJL',this.TJCJL],['量比',this.VOLRate],
+ ['平均K线',this.HeikinAshi], ["ADL", this.ADL],["SQJZ", this.SQJZ],["XT", this.XT],["CFJT", this.CFJT],["CYX",this.CYX],
+ ["WAVE",this.WAVE],
+ ['VOL-TDX',this.VOL_TDX],
+ ['EMPTY', this.EMPTY], //什么都不显示的指标
+ ['神奇九转', this.NineTurns],
+
+ //通达信特色指标
+ ["散户线", this.ShareholderCount],["NXTS", this.NXTS],["FKX", this.FKX],["两融资金", this.Margin4],
+ ["ZSDB",this.ZSDB],
+
+ ['CJL2', this.CJL], //期货持仓量
+ ['ASI', this.ASI],['DC', this.DC],['DEMA', this.DEMA],["VWAP", this.VWAP],
+
+ ['飞龙四式', this.Dragon4_Main],['飞龙四式-附图', this.Dragon4_Fig],
+ ['资金分析', this.FundsAnalysis],['融资占比',this.MarginProportion],['负面新闻', this.NewsNegative],
+ ['涨跌趋势', this.UpDownAnalyze],['北上资金', this.HK2SHSZ],['股东人数', this.ShareHolder],
+
+ ["两融余额", this.Margin2],["两融余额2", this.Margin3],
+
+ ['Zealink-资金吸筹', this.Zealink_Index1], ['Zealink-牛熊区间', this.Zealink_Index2],['Zealink-持仓信号', this.Zealink_Index3],
+ ['Zealink-增减持',this.Zealink_Index4],['Zealink-大宗交易', this.Zealink_Index5], ['Zealink-信托持股', this.Zealink_Index6],
+ ['Zealink-官网新闻', this.Zealink_Index7], ['Zealink-高管要闻', this.Zealink_Index8],['Zealink-股权质押', this.Zealink_Index9],
+ ['Zealink-操盘BS点', this.Zealink_Index10],['Zealink-操盘BS点2', this.Zealink_Index11],
+
+ //外包指标
+ ['放心股-操盘BS点',this.FXG_BSPoint],
+ ['放心股-涨停多空线',this.FXG_INDEX],
+ ['放心股-涨停吸筹区',this.FXG_INDEX2],
+ ['放心股-量能黄金点',this.FXG_INDEX3],
+
+ //五彩K线(函数COLOR_开头)
+ ['五彩K线-十字星',this.COLOR_KSTAR1],['五彩K线-早晨之星',this.COLOR_KSTAR2],['五彩K线-黄昏之星',this.COLOR_KSTAR3],['五彩K线-长十字',this.COLOR_SHI1],
+ ['五彩K线-身怀六甲',this.COLOR_K220],['五彩K线-三个白武士',this.COLOR_K300],['五彩K线-三只乌鸦',this.COLOR_K310],['五彩K线-光头阳线',this.COLOR_K380],
+ ['五彩K线-光脚阴线',this.COLOR_K390],['五彩K线-垂死十字',this.COLOR_K134],['五彩K线-早晨十字星',this.COLOR_K140],['五彩K线-黄昏十字星',this.COLOR_K150],
+ ['五彩K线-射击之星',this.COLOR_K160],['五彩K线-倒转锤头',this.COLOR_K165],['五彩K线-锤头',this.COLOR_K170],['五彩K线-吊颈',this.COLOR_K180],
+ ['五彩K线-穿头破脚',this.COLOR_K190],['五彩K线-出水芙蓉',this.COLOR_CSFR],['五彩K线-乌云盖顶',this.COLOR_WYGD],['五彩K线-曙光初现',this.COLOR_SGCJ],
+ ['五彩K线-十字胎',this.COLOR_SZTAI],['五彩K线-剑',this.COLOR_SWORD],['五彩K线-平顶',this.COLOR_PINGDING],['五彩K线-平底',this.COLOR_PINGDI],
+ ['五彩K线-大阳烛',this.COLOR_DAYANZHU],['五彩K线-大阴烛',this.COLOR_DAYINGZHU],
+
+ ['五彩K线-好友反攻',this.COLOR_HYFG],['五彩K线-跳空缺口',this.COLOR_TKQK],
+ ['五彩K线-双飞乌鸦',this.COLOR_SFWY],['五彩K线-上升三部曲',this.COLOR_SSSBQ],['五彩K线-下跌三部曲',this.COLOR_XDSBQ],['五彩K线-长下影',this.COLOR_CHXY],
+ ['五彩K线-长上影',this.COLOR_CHSY],['五彩K线-分离',this.COLOR_FENLI],
+
+ //交易系统
+ ['交易系统-BIAS',this.TRADE_BIAS],['交易系统-CCI',this.TRADE_CCI],['交易系统-DMI',this.TRADE_DMI],['交易系统-KD',this.TRADE_KD],
+ ['交易系统-BOLL',this.TRADE_BOLL],['交易系统-KDJ',this.TRADE_KDJ],['交易系统-MA',this.TRADE_MA],['交易系统-MACD',this.TRADE_MACD],
+ ['交易系统-MTM',this.TRADE_MTM],['交易系统-PSY',this.TRADE_PSY],['交易系统-ROC',this.TRADE_ROC],['交易系统-RSI',this.TRADE_RSI],
+ ['交易系统-VR',this.TRADE_VR],['交易系统-DPSJ',this.TRADE_DPSJ],
+
+ ['TEST', this.TEST] //测试用
+ ]);
+}
+
+JSIndexScript.AddIndex=function(aryIndex) //添加自定义指标
+{
+ for(var i in aryIndex)
+ {
+ g_CustomIndex.Add(aryIndex[i]);
+ }
+}
+
+JSIndexScript.prototype.Get=function(id)
+{
+ var data=g_CustomIndex.Get(id);
+ if (data) return data;
+
+ var func=this.DataMap.get(id);
+ if (func) return func();
+
+ return null;
+}
+
+JSIndexScript.prototype.Search=function(name)
+{
+ var result=[];
+ var reg = new RegExp(name,'i');
+ this.DataMap.forEach(function(value,key)
+ {
+ if (key.indexOf('交易系统-')!=0 && key.indexOf('五彩K线-')!=0 && key.search(reg)>=0)
+ result.push(key);
+ });
+
+ return result;
+}
+
+JSIndexScript.prototype.MA=function()
+{
+ let data=
+ {
+ Name:'MA', Description:'均线', IsMainIndex:true, StringFormat:2,
+ Args:[ { Name:'M1', Value:5}, { Name:'M2', Value:10 }, { Name:'M3', Value:20} ],
+ OutName:[ {Name:'MA1',DynamicName:"MA{M1}" }, {Name:'MA2',DynamicName:"MA{M2}" },{Name:'MA3',DynamicName:"MA{M3}" }],
+ Script: //脚本
+'MA1:MA(CLOSE,M1);\n\
+MA2:MA(CLOSE,M2);\n\
+MA3:MA(CLOSE,M3);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.MA4=function()
+{
+ let data=
+ {
+ Name:'MA', Description:'均线', IsMainIndex:true, StringFormat:2,
+ Args:[ { Name:'M1', Value:5}, { Name:'M2', Value:10 }, { Name:'M3', Value:20},{ Name:'M4', Value:60} ],
+ OutName:[ {Name:'MA1',DynamicName:"MA{M1}" }, {Name:'MA2',DynamicName:"MA{M2}" },{Name:'MA3',DynamicName:"MA{M3}" },{Name:'MA4',DynamicName:"MA{M4}" } ],
+ Script: //脚本
+'MA1:MA(CLOSE,M1);\n\
+MA2:MA(CLOSE,M2);\n\
+MA3:MA(CLOSE,M3);\n\
+MA4:MA(CLOSE,M4);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.MA5=function()
+{
+ let data=
+ {
+ Name:'MA', Description:'均线', IsMainIndex:true, StringFormat:2,
+ Args:[ { Name:'M1', Value:5}, { Name:'M2', Value:10 }, { Name:'M3', Value:20} ,{ Name:'M4', Value:60} ,{ Name:'M5', Value:0}],
+ OutName:[ {Name:'MA1',DynamicName:"MA{M1}" }, {Name:'MA2',DynamicName:"MA{M2}" },{Name:'MA3',DynamicName:"MA{M3}" },{Name:'MA4',DynamicName:"MA{M4}" },{Name:'MA5',DynamicName:"MA{M5}" } ],
+ Script: //脚本
+'MA1:MA(CLOSE,M1);\n\
+MA2:MA(CLOSE,M2);\n\
+MA3:MA(CLOSE,M3);\n\
+MA4:MA(CLOSE,M4);\n\
+MA5:MA(CLOSE,M5);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.MA6=function()
+{
+ let data=
+ {
+ Name:'MA', Description:'均线', IsMainIndex:true, StringFormat:2,
+ Args:
+ [
+ { Name:'M1', Value:5}, { Name:'M2', Value:10 }, { Name:'M3', Value:20} , { Name:'M4', Value:60} ,
+ { Name:'M5', Value:0},{ Name:'M6', Value:0}
+ ],
+ OutName:[ {Name:'MA1',DynamicName:"MA{M1}" }, {Name:'MA2',DynamicName:"MA{M2}" },{Name:'MA3',DynamicName:"MA{M3}" },{Name:'MA4',DynamicName:"MA{M4}" },
+ {Name:'MA5',DynamicName:"MA{M5}" } ,{ Name:'MA6',DynamicName:"MA{M6}" } ],
+ Script: //脚本
+'MA1:MA(CLOSE,M1);\n\
+MA2:MA(CLOSE,M2);\n\
+MA3:MA(CLOSE,M3);\n\
+MA4:MA(CLOSE,M4);\n\
+MA5:MA(CLOSE,M5);\n\
+MA6:MA(CLOSE,M6);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.MA7=function()
+{
+ let data=
+ {
+ Name:'MA', Description:'均线', IsMainIndex:true, StringFormat:2,
+ Args:
+ [
+ { Name:'M1', Value:5}, { Name:'M2', Value:10 }, { Name:'M3', Value:20}, { Name:'M4', Value:60},
+ { Name:'M5', Value:0},{ Name:'M6', Value:0} ,{ Name:'M7', Value:0 }
+ ],
+ OutName:[ {Name:'MA1',DynamicName:"MA{M1}" }, {Name:'MA2',DynamicName:"MA{M2}" },{Name:'MA3',DynamicName:"MA{M3}" },{Name:'MA4',DynamicName:"MA{M4}" },
+ {Name:'MA5',DynamicName:"MA{M5}" } ,{ Name:'MA6',DynamicName:"MA{M6}" } ,{ Name:'MA7',DynamicName:"MA{M7}" }],
+ Script: //脚本
+'MA1:MA(CLOSE,M1);\n\
+MA2:MA(CLOSE,M2);\n\
+MA3:MA(CLOSE,M3);\n\
+MA4:MA(CLOSE,M4);\n\
+MA5:MA(CLOSE,M5);\n\
+MA6:MA(CLOSE,M6);\n\
+MA7:MA(CLOSE,M7);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.MA8=function()
+{
+ let data=
+ {
+ Name:'MA', Description:'均线', IsMainIndex:true, StringFormat:2,
+ Args:
+ [
+ { Name:'M1', Value:5}, { Name:'M2', Value:10 }, { Name:'M3', Value:20}, { Name:'M4', Value:60},
+ { Name:'M5', Value:0},{ Name:'M6', Value:0} ,{ Name:'M7', Value:0 } ,{ Name:'M8', Value:0 }
+ ],
+ OutName:[ {Name:'MA1',DynamicName:"MA{M1}" }, {Name:'MA2',DynamicName:"MA{M2}" },{Name:'MA3',DynamicName:"MA{M3}" },{Name:'MA4',DynamicName:"MA{M4}" },
+ {Name:'MA5',DynamicName:"MA{M5}" } ,{ Name:'MA6',DynamicName:"MA{M6}" } ,{ Name:'MA7',DynamicName:"MA{M7}" },{ Name:'MA8',DynamicName:"MA{M8}" }],
+ Script: //脚本
+'MA1:MA(CLOSE,M1);\n\
+MA2:MA(CLOSE,M2);\n\
+MA3:MA(CLOSE,M3);\n\
+MA4:MA(CLOSE,M4);\n\
+MA5:MA(CLOSE,M5);\n\
+MA6:MA(CLOSE,M6);\n\
+MA7:MA(CLOSE,M7);\n\
+MA8:MA(CLOSE,M8);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.BOLL=function()
+{
+ let data=
+ {
+ Name:'BOLL', Description:'布林线', IsMainIndex:true,
+ Args:[ { Name:'M', Value:20} ],
+ Script: //脚本
+'BOLL:MA(CLOSE,M);\n\
+UB:BOLL+2*STD(CLOSE,M);\n\
+LB:BOLL-2*STD(CLOSE,M);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.BOLL2=function()
+{
+ let data=
+ {
+ Name:'BOLL2', Description:'布林线', IsMainIndex:false, KLineType:0,
+ Args:[ { Name:'M', Value:20} ],
+ Script: //脚本
+'BOLL:MA(CLOSE,M);\n\
+UB:BOLL+2*STD(CLOSE,M);\n\
+LB:BOLL-2*STD(CLOSE,M);'
+
+ };
+
+ return data;
+}
+
+
+JSIndexScript.prototype.BBI=function()
+{
+ let data=
+ {
+ Name:'BBI', Description:'多空均线', IsMainIndex:true,
+ Args:[ { Name:'M1', Value:3}, { Name:'M2', Value:6}, { Name:'M3', Value:12}, { Name:'M4', Value:24} ],
+ Script: //脚本
+ 'BBI:(MA(CLOSE,M1)+MA(CLOSE,M2)+MA(CLOSE,M3)+MA(CLOSE,M4))/4;'
+
+ };
+
+ return data;
+}
+
+
+JSIndexScript.prototype.DKX=function()
+{
+ let data=
+ {
+ Name:'DKX', Description:'多空线', IsMainIndex:false,
+ Args:[ { Name:'M', Value:10} ],
+ Script: //脚本
+'MID:=(3*CLOSE+LOW+OPEN+HIGH)/6;\n\
+DKX:(20*MID+19*REF(MID,1)+18*REF(MID,2)+17*REF(MID,3)+\n\
+16*REF(MID,4)+15*REF(MID,5)+14*REF(MID,6)+\n\
+13*REF(MID,7)+12*REF(MID,8)+11*REF(MID,9)+\n\
+10*REF(MID,10)+9*REF(MID,11)+8*REF(MID,12)+\n\
+7*REF(MID,13)+6*REF(MID,14)+5*REF(MID,15)+\n\
+4*REF(MID,16)+3*REF(MID,17)+2*REF(MID,18)+REF(MID,20))/210;\n\
+MADKX:MA(DKX,M);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.MIKE=function()
+{
+ let data=
+ {
+ Name:'MIKE', Description:'麦克支撑压力', IsMainIndex:true,
+ Args:[ { Name:'N', Value:10} ],
+ Script: //脚本
+'HLC:=REF(MA((HIGH+LOW+CLOSE)/3,N),1);\n\
+HV:=EMA(HHV(HIGH,N),3);\n\
+LV:=EMA(LLV(LOW,N),3);\n\
+STOR:EMA(2*HV-LV,3);\n\
+MIDR:EMA(HLC+HV-LV,3);\n\
+WEKR:EMA(HLC*2-LV,3);\n\
+WEKS:EMA(HLC*2-HV,3);\n\
+MIDS:EMA(HLC-HV+LV,3);\n\
+STOS:EMA(2*LV-HV,3);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.PBX=function()
+{
+ let data=
+ {
+ Name:'PBX', Description:'瀑布线', IsMainIndex:true,
+ Args:[ { Name:'M1', Value:4}, { Name:'M2', Value:6}, { Name:'M3', Value:9}, { Name:'M4', Value:13},{ Name:'M5', Value:18},{ Name:'M6', Value:24} ],
+ Script: //脚本
+'PBX1:(EMA(CLOSE,M1)+MA(CLOSE,M1*2)+MA(CLOSE,M1*4))/3;\n\
+PBX2:(EMA(CLOSE,M2)+MA(CLOSE,M2*2)+MA(CLOSE,M2*4))/3;\n\
+PBX3:(EMA(CLOSE,M3)+MA(CLOSE,M3*2)+MA(CLOSE,M3*4))/3;\n\
+PBX4:(EMA(CLOSE,M4)+MA(CLOSE,M4*2)+MA(CLOSE,M4*4))/3;\n\
+PBX5:(EMA(CLOSE,M5)+MA(CLOSE,M5*2)+MA(CLOSE,M5*4))/3;\n\
+PBX6:(EMA(CLOSE,M6)+MA(CLOSE,M6*2)+MA(CLOSE,M6*4))/3;'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.ENE=function()
+{
+ let data=
+ {
+ Name:'ENE', Description:'轨道线', IsMainIndex:true,
+ Args:[ { Name:'N', Value:25}, { Name:'M1', Value:6}, { Name:'M2', Value:6} ],
+ Script: //脚本
+'UPPER:(1+M1/100)*MA(CLOSE,N);\n\
+LOWER:(1-M2/100)*MA(CLOSE,N);\n\
+ENE:(UPPER+LOWER)/2;'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.MACD=function()
+{
+ let data=
+ {
+ Name:'MACD', Description:'平滑异同平均', IsMainIndex:false,
+ Args:[ { Name:'SHORT', Value:12}, { Name:'LONG', Value:26}, { Name:'MID', Value:9} ],
+ Script: //脚本
+'DIF:EMA(CLOSE,SHORT)-EMA(CLOSE,LONG);\n\
+DEA:EMA(DIF,MID);\n\
+MACD:(DIF-DEA)*2,COLORSTICK;'
+
+ };
+
+ return data;
+}
+
+//上下柱子
+JSIndexScript.prototype.MACD2=function()
+{
+ let data=
+ {
+ Name:'MACD', Description:'平滑异同平均', IsMainIndex:false,
+ Args:[ { Name:'SHORT', Value:12}, { Name:'LONG', Value:26}, { Name:'MID', Value:9} ],
+ Script: //脚本
+'DIF2:=EMA(CLOSE,SHORT)-EMA(CLOSE,LONG);\n\
+DEA2:=EMA(DIF2,MID);\n\
+MACD:(DIF2-DEA2)*2,COLORSTICK,LINETHICK50;\n\
+DIF:DIF2;\n\
+DEA:DEA2;'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.KDJ=function()
+{
+ let data=
+ {
+ Name:'KDJ', Description:'随机指标', IsMainIndex:false,
+ Args:[ { Name:'N', Value:9}, { Name:'M1', Value:3}, { Name:'M2', Value:3} ],
+ Script: //脚本
+'RSV:=(CLOSE-LLV(LOW,N))/(HHV(HIGH,N)-LLV(LOW,N))*100;\n\
+K:SMA(RSV,M1,1);\n\
+D:SMA(K,M2,1);\n\
+J:3*K-2*D;'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.VOL=function()
+{
+ let data=
+ {
+ Name:'VOL', Description:'成交量', IsMainIndex:false,FloatPrecision:0,
+ Args:[ { Name:'M1', Value:5}, { Name:'M2', Value:10} ],
+ OutName:[ {Name:'MA1',DynamicName:"MA{M1}" }, {Name:'MA2',DynamicName:"MA{M2}" }],
+ Script: //脚本
+'VOL:VOL,VOLSTICK;\n\
+MA1:MA(VOL,M1);\n\
+MA2:MA(VOL,M2);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.VOL_TDX=function()
+{
+ let data=
+ {
+ Name:'VOL-TDX', Description:'成交量(虚拟)', IsMainIndex:false,FloatPrecision:0,
+ Args:[ { Name:'M1', Value:5}, { Name:'M2', Value:10} ],
+ Script: //脚本
+'TOTAL:=IF(PERIOD=1,5,IF(PERIOD=2,15,IF(PERIOD=3,30,IF(PERIOD=4,60,IF(PERIOD=5,TOTALFZNUM,1)))));\n\
+MTIME:=MOD(FROMOPEN,TOTAL);\n\
+CTIME:=IF(MTIME<0.5,TOTAL,MTIME);\n\
+VVOL:IF((CURRBARSCOUNT=1 AND DYNAINFO(8)>1),VOL*(TOTAL+3)/(CTIME+3),DRAWNULL),NODRAW;\n\
+STICKLINE((CURRBARSCOUNT=1 AND DYNAINFO(8)>1),VVOL,0,-1,-1),COLORYELLOW;\n\
+VOLUME:VOL,VOLSTICK;\n\
+MAVOL1:MA(VOLUME,M1);\n\
+MAVOL2:MA(VOLUME,M2);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.RSI=function()
+{
+ let data=
+ {
+ Name:'RSI', Description:'相对强弱指标', IsMainIndex:false,
+ Args:[ { Name:'N1', Value:6}, { Name:'N2', Value:12}, { Name:'N3', Value:24} ],
+ Script: //脚本
+'LC:=REF(CLOSE,1);\n\
+RSI1:SMA(MAX(CLOSE-LC,0),N1,1)/SMA(ABS(CLOSE-LC),N1,1)*100;\n\
+RSI2:SMA(MAX(CLOSE-LC,0),N2,1)/SMA(ABS(CLOSE-LC),N2,1)*100;\n\
+RSI3:SMA(MAX(CLOSE-LC,0),N3,1)/SMA(ABS(CLOSE-LC),N3,1)*100;'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.BRAR=function()
+{
+ let data=
+ {
+ Name:'BRAR', Description:'情绪指标', IsMainIndex:false,
+ Args:[ { Name:'N', Value:26} ],
+ Script: //脚本
+'BR:SUM(MAX(0,HIGH-REF(CLOSE,1)),N)/SUM(MAX(0,REF(CLOSE,1)-LOW),N)*100;\n\
+AR:SUM(HIGH-OPEN,N)/SUM(OPEN-LOW,N)*100;'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.WR=function()
+{
+ let data=
+ {
+ Name:'WR', Description:'威廉指标', IsMainIndex:false,
+ Args:[ { Name:'N', Value:10}, { Name:'N1', Value:6} ],
+ Script: //脚本
+'WR1:100*(HHV(HIGH,N)-CLOSE)/(HHV(HIGH,N)-LLV(LOW,N));\n\
+WR2:100*(HHV(HIGH,N1)-CLOSE)/(HHV(HIGH,N1)-LLV(LOW,N1));'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.BIAS=function()
+{
+ let data=
+ {
+ Name:'BIAS', Description:'乖离率', IsMainIndex:false,
+ Args:[ { Name:'N1', Value:6}, { Name:'N2', Value:12}, { Name:'N3', Value:24} ],
+ Script: //脚本
+'BIAS1 :(CLOSE-MA(CLOSE,N1))/MA(CLOSE,N1)*100;\n\
+BIAS2 :(CLOSE-MA(CLOSE,N2))/MA(CLOSE,N2)*100;\n\
+BIAS3 :(CLOSE-MA(CLOSE,N3))/MA(CLOSE,N3)*100;'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.OBV=function()
+{
+ let data=
+ {
+ Name:'OBV', Description:'累积能量线', IsMainIndex:false,
+ Args:[ { Name:'M', Value:30} ],
+ Script: //脚本
+'VA:=IF(CLOSE>REF(CLOSE,1),VOL,-VOL);\n\
+OBV:SUM(IF(CLOSE==REF(CLOSE,1),0,VA),0);\n\
+MAOBV:MA(OBV,M);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.DMI=function()
+{
+ let data=
+ {
+ Name:'DMI', Description:'趋向指标', IsMainIndex:false,
+ Args:[ { Name:'N', Value:14}, { Name:'MM', Value:6} ],
+ Script: //脚本
+'MTR:=EXPMEMA(MAX(MAX(HIGH-LOW,ABS(HIGH-REF(CLOSE,1))),ABS(REF(CLOSE,1)-LOW)),N);\n\
+HD :=HIGH-REF(HIGH,1);\n\
+LD :=REF(LOW,1)-LOW;\n\
+DMP:=EXPMEMA(IF(HD>0&&HD>LD,HD,0),N);\n\
+DMM:=EXPMEMA(IF(LD>0&&LD>HD,LD,0),N);\n\
+PDI: DMP*100/MTR;\n\
+MDI: DMM*100/MTR;\n\
+ADX: EXPMEMA(ABS(MDI-PDI)/(MDI+PDI)*100,MM);\n\
+ADXR:EXPMEMA(ADX,MM);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.CR=function()
+{
+ let data=
+ {
+ Name:'CR', Description:'带状能量线', IsMainIndex:false,
+ Args:[ { Name:'N', Value:26}, { Name:'M1', Value:10},{ Name:'M2', Value:20},{ Name:'M3', Value:40},{ Name:'M4', Value:62} ],
+ Script: //脚本
+'MID:=REF(HIGH+LOW,1)/2;\n\
+CR:SUM(MAX(0,HIGH-MID),N)/SUM(MAX(0,MID-LOW),N)*100;\n\
+MA1:REF(MA(CR,M1),M1/2.5+1);\n\
+MA2:REF(MA(CR,M2),M2/2.5+1);\n\
+MA3:REF(MA(CR,M3),M3/2.5+1);\n\
+MA4:REF(MA(CR,M4),M4/2.5+1);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.PSY=function()
+{
+ let data=
+ {
+ Name:'PSY', Description:'心理线', IsMainIndex:false,
+ Args:[ { Name:'N', Value:12}, { Name:'M', Value:6} ],
+ Script: //脚本
+'PSY:COUNT(CLOSE>REF(CLOSE,1),N)/N*100;\r\
+PSYMA:MA(PSY,M);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.CCI=function()
+{
+ let data=
+ {
+ Name:'CCI', Description:'商品路径指标', IsMainIndex:false,
+ Args:[ { Name:'N', Value:14} ],
+ Script: //脚本
+'TYP:=(HIGH+LOW+CLOSE)/3;\n\
+CCI:(TYP-MA(TYP,N))/(0.015*AVEDEV(TYP,N));'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.DMA=function()
+{
+ let data=
+ {
+ Name:'DMA', Description:'平均差', IsMainIndex:false,
+ Args:[ { Name:'N1', Value:10},{ Name:'N2', Value:50},{ Name:'M', Value:10} ],
+ Script: //脚本
+'DIF:MA(CLOSE,N1)-MA(CLOSE,N2);\n\
+DIFMA:MA(DIF,M);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.TRIX=function()
+{
+ let data=
+ {
+ Name:'TRIX', Description:'三重指数平均线', IsMainIndex:false,
+ Args:[ { Name:'N', Value:12},{ Name:'M', Value:9} ],
+ Script: //脚本
+'MTR:=EMA(EMA(EMA(CLOSE,N),N),N);\n\
+TRIX:(MTR-REF(MTR,1))/REF(MTR,1)*100;\n\
+MATRIX:MA(TRIX,M) ;'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.VR=function()
+{
+ let data=
+ {
+ Name:'VR', Description:'成交量变异率', IsMainIndex:false,
+ Args:[ { Name:'N', Value:26},{ Name:'M', Value:6} ],
+ Script: //脚本
+'TH:=SUM(IF(CLOSE>REF(CLOSE,1),VOL,0),N);\n\
+TL:=SUM(IF(CLOSE][REF(CLOSE,1),MIDA,MIDB),0);\n\
+MAWAD:MA(WAD,M);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.CHO=function()
+{
+ let data=
+ {
+ Name:'CHO', Description:'佳庆指标', IsMainIndex:false,
+ Args:[ { Name:'N1', Value:10}, { Name:'N2', Value:20}, { Name:'M', Value:6}],
+ Script: //脚本
+'MID:=SUM(VOL*(2*CLOSE-HIGH-LOW)/(HIGH+LOW),0);\n\
+CHO:MA(MID,N1)-MA(MID,N2);\n\
+MACHO:MA(CHO,M);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.ADTM=function()
+{
+ let data=
+ {
+ Name:'ADTM', Description:'动态买卖气指标', IsMainIndex:false,
+ Args:[ { Name:'N', Value:23}, { Name:'M', Value:8}],
+ Script: //脚本
+'DTM:=IF(OPEN<=REF(OPEN,1),0,MAX((HIGH-OPEN),(OPEN-REF(OPEN,1))));\n\
+DBM:=IF(OPEN>=REF(OPEN,1),0,MAX((OPEN-LOW),(OPEN-REF(OPEN,1))));\n\
+STM:=SUM(DTM,N);\n\
+SBM:=SUM(DBM,N);\n\
+ADTM:IF(STM>SBM,(STM-SBM)/STM,IF(STM==SBM,0,(STM-SBM)/SBM));\n\
+MAADTM:MA(ADTM,M);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.HSL=function()
+{
+ let data=
+ {
+ Name:'HSL', Description:'换手线', IsMainIndex:false,
+ Args:[ { Name:'N', Value:5} ],
+ Script: //脚本
+'HSL:IF((SETCODE==0||SETCODE==1),100*VOL,VOL)/(FINANCE(7)/100);\n\
+MAHSL:MA(HSL,N);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.BIAS36=function()
+{
+ let data=
+ {
+ Name:'BIAS36', Description:'三六乖离', IsMainIndex:false,
+ Args:[ { Name:'M', Value:6} ],
+ Script: //脚本
+'BIAS36:MA(CLOSE,3)-MA(CLOSE,6);\n\
+BIAS612:MA(CLOSE,6)-MA(CLOSE,12);\n\
+MABIAS:MA(BIAS36,M);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.BIAS_QL=function()
+{
+ let data=
+ {
+ Name:'BIAS_QL', Description:'乖离率-传统版', IsMainIndex:false,
+ Args:[ { Name:'N', Value:6}, { Name:'M', Value:6} ],
+ Script: //脚本
+'BIAS :(CLOSE-MA(CLOSE,N))/MA(CLOSE,N)*100;\n\
+BIASMA :MA(BIAS,M);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.DPO=function()
+{
+ let data=
+ {
+ Name:'DPO', Description:'区间震荡线', IsMainIndex:false,
+ Args:[ { Name:'N', Value:20}, { Name:'M', Value:6} ],
+ Script: //脚本
+'DPO:CLOSE-REF(MA(CLOSE,N),N/2+1);\n\
+MADPO:MA(DPO,M);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.OSC=function()
+{
+ let data=
+ {
+ Name:'OSC', Description:'变动速率线', IsMainIndex:false,
+ Args:[ { Name:'N', Value:20}, { Name:'M', Value:6} ],
+ Script: //脚本
+'OSC:100*(CLOSE-MA(CLOSE,N));\n\
+MAOSC:EXPMEMA(OSC,M);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.ATR=function()
+{
+ let data=
+ {
+ Name:'ATR', Description:'真实波幅', IsMainIndex:false,
+ Args:[ { Name:'N', Value:14}],
+ Script: //脚本
+'MTR:MAX(MAX((HIGH-LOW),ABS(REF(CLOSE,1)-HIGH)),ABS(REF(CLOSE,1)-LOW));\n\
+ATR:MA(MTR,N);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.NVI=function()
+{
+ let data=
+ {
+ Name:'ATR', Description:'负成交量', IsMainIndex:false,
+ Args:[ { Name:'N', Value:72} ],
+ Script: //脚本
+'NVI:100*MULAR(IF(V][REF(V,1),C/REF(C,1),1),0);\n\
+MANVI:MA(NVI,N);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.UOS=function()
+{
+ let data=
+ {
+ Name:'UOS', Description:'终极指标', IsMainIndex:false,
+ Args:[ { Name:'N1', Value:7} ,{ Name:'N2', Value:14},{ Name:'N3', Value:28},{ Name:'M', Value:6}],
+ Script: //脚本
+'TH:=MAX(HIGH,REF(CLOSE,1));\n\
+TL:=MIN(LOW,REF(CLOSE,1));\n\
+ACC1:=SUM(CLOSE-TL,N1)/SUM(TH-TL,N1);\n\
+ACC2:=SUM(CLOSE-TL,N2)/SUM(TH-TL,N2);\n\
+ACC3:=SUM(CLOSE-TL,N3)/SUM(TH-TL,N3);\n\
+UOS:(ACC1*N2*N3+ACC2*N1*N3+ACC3*N1*N2)*100/(N1*N2+N1*N3+N2*N3);\n\
+MAUOS:EXPMEMA(UOS,M);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.CYW=function()
+{
+ let data=
+ {
+ Name:'CYW', Description:'主力控盘', IsMainIndex:false,
+ Args:[ ],
+ Script: //脚本
+'VAR1:=CLOSE-LOW;\n\
+VAR2:=HIGH-LOW;\n\
+VAR3:=CLOSE-HIGH;\n\
+VAR4:=IF(HIGH>LOW,(VAR1/VAR2+VAR3/VAR2)*VOL,0);\n\
+CYW: SUM(VAR4,10)/10000, COLORSTICK;'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.LON=function()
+{
+ let data=
+ {
+ Name:'LON', Description:'龙系长线', IsMainIndex:false,
+ Args:[ { Name:'N', Value:10} ],
+ Script: //脚本
+'LC := REF(CLOSE,1);\n\
+VID := SUM(VOL,2)/(((HHV(HIGH,2)-LLV(LOW,2)))*100);\n\
+RC := (CLOSE-LC)*VID;\n\
+LONG := SUM(RC,0);\n\
+DIFF := SMA(LONG,10,1);\n\
+DEA := SMA(LONG,20,1);\n\
+LON : DIFF-DEA;\n\
+LONMA : MA(LON,10);\n\
+LONT : LON, COLORSTICK;'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.NDB = function ()
+{
+ let data =
+ {
+ Name: 'NDB', Description: '脑电波', IsMainIndex: false,
+ Args: [{ Name: 'P1', Value: 5 }, { Name: 'P2', Value: 10 }],
+ Script: //脚本
+'HH:=IF(C/REF(C,1)>1.098 AND L>REF(H,1),2*C-REF(C,1)-H,2*C-H-L);\n\
+V1:= BARSCOUNT(C) - 1;\n\
+V2:= 2 * REF(C, V1) - REF(H, V1) - REF(L, V1);\n\
+DK: SUM(HH, 0) + V2;\n\
+MDK5: MA(DK, P1);\n\
+MDK10: MA(DK, P2);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.SKDJ = function ()
+{
+ let data =
+ {
+ Name: 'SKDJ', Description: '慢速随机指标', IsMainIndex: false,
+ Args: [{ Name: 'N', Value: 9 }, { Name: 'M', Value: 3 }],
+ Script: //脚本
+'LOWV:=LLV(LOW,N);\n\
+HIGHV:=HHV(HIGH,N);\n\
+RSV:=EMA((CLOSE-LOWV)/(HIGHV-LOWV)*100,M);\n\
+K:EMA(RSV,M);\n\
+D:MA(K,M);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.KD = function ()
+{
+ let data =
+ {
+ Name: 'KD', Description: '随机指标KD', IsMainIndex: false,
+ Args: [{ Name: 'N', Value: 9 }, { Name: 'M1', Value: 3 },{ Name: 'M2', Value: 3 }],
+ Script: //脚本
+'RSV:=(CLOSE-LLV(LOW,N))/(HHV(HIGH,N)-LLV(LOW,N))*100;\n\
+K:SMA(RSV,M1,1);\n\
+D:SMA(K,M2,1);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.FKX=function()
+{
+ let data=
+ {
+ Name:'FKX', Description:'反K线', IsMainIndex:true,
+ Args:[ ],
+ Script: //脚本
+ 'DRAWKLINE(-LOW, -OPEN, -HIGH, -CLOSE);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.DKCOL = function ()
+{
+ let data =
+ {
+ Name: 'DKCOL', Description: '多空能量柱(适用于分时主图)', IsMainIndex: true,
+ Args: [{ Name: 'N', Value: 5 }],
+ Script: //脚本
+'FF:=(C-REF(C,N))/REF(C,N);\n\
+STICKLINE(FF>0,DYNAINFO(3),DYNAINFO(3)*(1+FF),0.5,0),COLORRED;\n\
+STICKLINE(FF<0,DYNAINFO(3),DYNAINFO(3)*(1+FF),0.5,0),COLORGREEN;'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.UDL = function ()
+{
+ let data =
+ {
+ Name: 'UDL', Description: '引力线', IsMainIndex: false,
+ Args: [{ Name: 'N1', Value: 3 },{ Name: 'N2', Value: 5 },{ Name: 'N3', Value: 10 },{ Name: 'N4', Value: 20 },{ Name: 'M', Value: 6 }],
+ Script: //脚本
+'UDL:(MA(CLOSE,N1)+MA(CLOSE,N2)+MA(CLOSE,N3)+MA(CLOSE,N4))/4;\n\
+MAUDL:MA(UDL,M);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.MFI = function ()
+{
+ let data =
+ {
+ Name: 'MFI', Description: '资金流量指标', IsMainIndex: false,
+ Args: [{ Name: 'N', Value: 14 },{ Name: 'N2', Value: 6 }],
+ Script: //脚本
+'TYP := (HIGH + LOW + CLOSE)/3;\n\
+V1:=SUM(IF(TYP>REF(TYP,1),TYP*VOL,0),N)/SUM(IF(TYP][=0,DIF,0);\n\
+VD:=IF(DIF<0,-DIF,0);\n\
+MAU1:=MEMA(VU,M1);\n\
+MAD1:=MEMA(VD,M1);\n\
+MAU2:=MEMA(VU,M2);\n\
+MAD2:=MEMA(VD,M2);\n\
+RSI10:MA(100*MAU1/(MAU1+MAD1),M1);\n\
+RSI6:MA(100*MAU2/(MAU2+MAD2),M2);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.CYD = function ()
+{
+ let data =
+ {
+ Name: 'CYD', Description: '承接因子', IsMainIndex: false,
+ Args: [{ Name: 'N', Value: 21 }],
+ Script: //脚本
+'CYDS:WINNER(CLOSE)/(VOL/CAPITAL);\n\
+CYDN:WINNER(CLOSE)/MA(VOL/CAPITAL,N);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.CYF = function ()
+{
+ let data =
+ {
+ Name: 'CYF', Description: '市场能量', IsMainIndex: false,
+ Args: [{ Name: 'N', Value: 21 }],
+ Script: //脚本
+'CYF:100-100/(1+EMA(HSL,N));'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.TAPI = function ()
+{
+ let data =
+ {
+ Name: 'TAPI', Description: '加权指数成交值', IsMainIndex: false,
+ Args: [{ Name: 'M', Value: 6 }],
+ Script: //脚本
+'TAPI:AMOUNT/INDEXC;\n\
+MATAIP:MA(TAPI,M);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.VMACD = function ()
+{
+ let data =
+ {
+ Name: 'VMACD', Description: '量平滑异同平均', IsMainIndex: false,
+ Args: [{ Name: 'SHORT', Value: 12 },{ Name: 'LONG', Value: 26 },{ Name: 'MID', Value: 9 }],
+ Script: //脚本
+'DIF:EMA(VOL,SHORT)-EMA(VOL,LONG);\n\
+DEA:EMA(DIF,MID);\n\
+MACD:DIF-DEA,COLORSTICK;'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.QACD = function ()
+{
+ let data =
+ {
+ Name: 'QACD', Description: '快速异同平均', IsMainIndex: false,
+ Args: [{ Name: 'N1', Value: 12 },{ Name: 'N2', Value: 26 },{ Name: 'M', Value: 9 }],
+ Script: //脚本
+'DIF:EMA(CLOSE,N1)-EMA(CLOSE,N2);\n\
+MACD:EMA(DIF,M);\n\
+DDIF:DIF-MACD;'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.VPT = function ()
+{
+ let data =
+ {
+ Name: 'VPT', Description: '量价曲线', IsMainIndex: false,
+ Args: [{ Name: 'N', Value: 51 },{ Name: 'M', Value: 6 }],
+ Script: //脚本
+'VPT:SUM(VOL*(CLOSE-REF(CLOSE,1))/REF(CLOSE,1),N);\n\
+MAVPT:MA(VPT,M);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.WVAD = function ()
+{
+ let data =
+ {
+ Name: 'WVAD', Description: '威廉变异离散量', IsMainIndex: false,
+ Args: [{ Name: 'N', Value: 24 },{ Name: 'M', Value: 6 }],
+ Script: //脚本
+'WVAD:SUM((CLOSE-OPEN)/(HIGH-LOW)*VOL,N)/10000;\n\
+MAWVAD:MA(WVAD,M);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.DBQR = function ()
+{
+ let data =
+ {
+ Name: 'WVAD', Description: '对比强弱', IsMainIndex: false,
+ Args: [{ Name: 'N', Value: 5 },{ Name: 'M1', Value: 10 },{ Name: 'M2', Value: 20 },{ Name: 'M3', Value: 60 }],
+ Script: //脚本
+'ZS:(INDEXC-REF(INDEXC,N))/REF(INDEXC,N);\n\
+GG:(CLOSE-REF(CLOSE,N))/REF(CLOSE,N);\n\
+MADBQR1:MA(GG,M1);\n\
+MADBQR2:MA(GG,M2);\n\
+MADBQR3:MA(GG,M3);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.JS = function ()
+{
+ let data =
+ {
+ Name: 'JS', Description: '加速线', IsMainIndex: false,
+ Args: [{ Name: 'N', Value: 5 },{ Name: 'M1', Value: 5 },{ Name: 'M2', Value: 10 },{ Name: 'M3', Value: 20 }],
+ Script: //脚本
+'JS:100*(CLOSE-REF(CLOSE,N))/(N*REF(CLOSE,N));\n\
+MAJS1:MA(JS,M1);\n\
+MAJS2:MA(JS,M2);\n\
+MAJS3:MA(JS,M3);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.CYE = function ()
+{
+ let data =
+ {
+ Name: 'CYE', Description: '市场趋势', IsMainIndex: false,
+ Args: [ ],
+ Script: //脚本
+'MAL:=MA(CLOSE,5);\n\
+MAS:=MA(MA(CLOSE,20),5);\n\
+CYEL:(MAL-REF(MAL,1))/REF(MAL,1)*100;\n\
+CYES:(MAS-REF(MAS,1))/REF(MAS,1)*100;'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.QR = function ()
+{
+ let data =
+ {
+ Name: 'QR', Description: '强弱指标', IsMainIndex: false,
+ Args: [{ Name: 'N', Value: 21 } ],
+ Script: //脚本
+'个股: (CLOSE-REF(CLOSE,N))/REF(CLOSE,N)*100; \n\
+大盘: (INDEXC-REF(INDEXC,N))/REF(INDEXC,N)*100; \n\
+强弱值:EMA(个股-大盘,2),COLORSTICK;'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.GDX = function ()
+{
+ let data =
+ {
+ Name: 'GDX', Description: '轨道线', IsMainIndex: false,
+ Args: [{ Name: 'N', Value: 30 } ,{ Name: 'M', Value: 9 }],
+ Script: //脚本
+'AA:=ABS((2*CLOSE+HIGH+LOW)/4-MA(CLOSE,N))/MA(CLOSE,N); \n\
+轨道:DMA(CLOSE,AA);\n\
+压力线:(1+M/100)*轨道; \n\
+支撑线:(1-M/100)*轨道;'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.JLHB = function ()
+{
+ let data =
+ {
+ Name: 'JLHB', Description: '绝路航标', IsMainIndex: false,
+ Args: [{ Name: 'N', Value: 7 } ,{ Name: 'M', Value: 5 }],
+ Script: //脚本
+'VAR1:=(CLOSE-LLV(LOW,60))/(HHV(HIGH,60)-LLV(LOW,60))*80; \n\
+B:SMA(VAR1,N,1); \n\
+VAR2:SMA(B,M,1); \n\
+绝路航标:IF(CROSS(B,VAR2) AND B<40,50,0);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.PCNT = function ()
+{
+ let data =
+ {
+ Name: 'PCNT', Description: '幅度比', IsMainIndex: false,
+ Args: [{ Name: 'M', Value: 5 }],
+ Script: //脚本
+'PCNT:(CLOSE-REF(CLOSE,1))/CLOSE*100;\n\
+MAPCNT:EXPMEMA(PCNT,M);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.BTX = function ()
+{
+ let data =
+ {
+ Name: 'BTX', Description: '宝塔线', IsMainIndex: false,
+ Args: [],
+ Script: //脚本
+ 'B1:=REF(C,1);\n\
+B2:= REF(C, 2);\n\
+SS:= IF(C > REF(C, 1) AND REF(C, 1) >= REF(C, 2), 1, IF(C < REF(C, 1) AND REF(C, 1) <= REF(C, 2), -1, IF(C > REF(C, 2) AND REF(C, 2) > REF(C, 1), 2, IF(C < REF(C, 2) AND REF(C, 2) < REF(C, 1), -2, 0))));\n\
+SM:= IF(REF(SS, 1) <> 0, REF(SS, 1), IF(REF(SS, 2) <> 0, REF(SS, 2), IF(REF(SS, 3) <> 0, REF(SS, 3), IF(REF(SS, 5) <> 0, REF(SS, 5), IF(REF(SS, 6) <> 0, REF(SS, 6), IF(REF(SS, 7) <> 0, REF(SS, 7), 0))))));\n\
+MC:= IF(REF(SS, 1) <> 0, B2, IF(SM > 0, MIN(B1, B2), MAX(B1, B2)));\n\
+TOW1:= IF(C > REF(C, 1), C, REF(C, 1));\n\
+TOW2:= IF((SS == -1 OR SS == -2) AND SM > 0, B2, TOW1);\n\
+TOWER:= IF(TOW1 > TOW2, TOW1, TOW2);\n\
+STICKLINE(SS == 1 OR SM >= 1 AND SS == 0, B1, C, 10, 1), COLORRED;\n\
+STICKLINE(SS == -1 OR SM <= -1 AND SS == 0, B1, C, 10, 0), COLORCYAN;\n\
+STICKLINE(SS == 2, B2, C, 10, 1), COLORRED;\n\
+STICKLINE(SS == -2, B2, C, 10, 0), COLORCYAN;\n\
+STICKLINE((SS == -1 OR SS == -2) AND SM > 0, B2, B1, 10, 1), COLORRED;\n\
+STICKLINE((SS == 1 OR SS == 2) AND SM < 0, B2, B1, 10, 0), COLORCYAN;'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.AMO = function ()
+{
+ let data =
+ {
+ Name: 'AMO', Description: '成交金额', IsMainIndex: false,
+ Args: [{ Name: 'M1', Value: 5 },{ Name: 'M2', Value: 10 }],
+ Script: //脚本
+'AMOW:AMOUNT/10000.0,VOLSTICK;\n\
+AMO1:MA(AMOW,M1);\n\
+AMO2:MA(AMOW,M2);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.VRSI = function ()
+{
+ let data =
+ {
+ Name: 'VRSI', Description: '相对强弱量', IsMainIndex: false,
+ Args: [{ Name: 'N1', Value: 6 },{ Name: 'N2', Value: 12 },{ Name: 'N3', Value: 24 }],
+ Script: //脚本
+'LC:=REF(VOL,1);\n\
+RSI1:SMA(MAX(VOL-LC,0),N1,1)/SMA(ABS(VOL-LC),N1,1)*100;\n\
+RSI2:SMA(MAX(VOL-LC,0),N2,1)/SMA(ABS(VOL-LC),N2,1)*100;\n\
+RSI3:SMA(MAX(VOL-LC,0),N3,1)/SMA(ABS(VOL-LC),N3,1)*100;'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.HSCOL = function ()
+{
+ let data =
+ {
+ Name: 'HSCOL', Description: '换手柱', IsMainIndex: false,
+ Args: [{ Name: 'N', Value: 5 }],
+ Script: //脚本
+'HSCOL:IF((SETCODE==0||SETCODE==1),100*VOL,VOL)/(FINANCE(7)/100),VOLSTICK;\n\
+MAHSL:MA(HSCOL,N);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.DBQRV = function ()
+{
+ let data =
+ {
+ Name: 'DBQRV', Description: '对比强弱量(需下载日线)', IsMainIndex: false,
+ Args: [{ Name: 'N', Value: 5 }],
+ Script: //脚本
+'ZS:(INDEXV-REF(INDEXV,N))/REF(INDEXV,N);\n\
+GG:(VOL-REF(VOL,N))/REF(VOL,N);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.DBLB = function ()
+{
+ let data =
+ {
+ Name: 'DBLB', Description: '对比量比(需下载日线)', IsMainIndex: false,
+ Args: [{ Name: 'N', Value: 5 },{ Name: 'M', Value: 5 }],
+ Script: //脚本
+'GG:=VOL/SUM(REF(VOL,1),N);\n\
+ZS:=INDEXV/SUM(REF(INDEXV,1),N);\n\
+DBLB:GG/ZS;\n\
+MADBLB:MA(DBLB,M);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.ACD = function ()
+{
+ let data =
+ {
+ Name: 'ACD', Description: '升降线', IsMainIndex: false,
+ Args: [{ Name: 'M', Value: 20 }],
+ Script: //脚本
+'LC:=REF(CLOSE,1);\n\
+DIF:=CLOSE-IF(CLOSE>LC,MIN(LOW,LC),MAX(HIGH,LC));\n\
+ACD:SUM(IF(CLOSE==LC,0,DIF),0);\n\
+MAACD:EXPMEMA(ACD,M);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.EXPMA = function ()
+{
+ let data =
+ {
+ Name: 'EXPMA', Description: '指数平均线', IsMainIndex: true,
+ Args: [{ Name: 'M1', Value: 12 },{ Name: 'M2', Value: 50 }],
+ Script: //脚本
+'EXP1:EMA(CLOSE,M1);\n\
+EXP2:EMA(CLOSE,M2);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.EXPMA_S = function ()
+{
+ let data =
+ {
+ Name: 'EXPMA_S', Description: '指数平均线-副图', IsMainIndex: false,
+ Args: [{ Name: 'M1', Value: 12 },{ Name: 'M2', Value: 50 }],
+ Script: //脚本
+'EXP1:EMA(CLOSE,M1);\n\
+EXP2:EMA(CLOSE,M2);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.HMA = function ()
+{
+ let data =
+ {
+ Name: 'HMA', Description: '高价平均线', IsMainIndex: true,
+ Args: [{ Name: 'M1', Value: 6 },{ Name: 'M2', Value: 12 },{ Name: 'M3', Value: 30 },{ Name: 'M4', Value: 72 },{ Name: 'M5', Value: 144 }],
+ Script: //脚本
+'HMA1:MA(HIGH,M1);\n\
+HMA2:MA(HIGH,M2);\n\
+HMA3:MA(HIGH,M3);\n\
+HMA4:MA(HIGH,M4);\n\
+HMA5:MA(HIGH,M5);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.LMA = function ()
+{
+ let data =
+ {
+ Name: 'LMA', Description: '低价平均线', IsMainIndex: true,
+ Args: [{ Name: 'M1', Value: 6 },{ Name: 'M2', Value: 12 },{ Name: 'M3', Value: 30 },{ Name: 'M4', Value: 72 },{ Name: 'M5', Value: 144 }],
+ Script: //脚本
+'LMA1:MA(LOW,M1);\n\
+LMA2:MA(LOW,M2);\n\
+LMA3:MA(LOW,M3);\n\
+LMA4:MA(LOW,M4);\n\
+LMA5:MA(LOW,M5);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.VMA = function ()
+{
+ let data =
+ {
+ Name: 'VMA', Description: '变异平均线', IsMainIndex: true,
+ Args: [{ Name: 'M1', Value: 6 },{ Name: 'M2', Value: 12 },{ Name: 'M3', Value: 30 },{ Name: 'M4', Value: 72 },{ Name: 'M5', Value: 144 }],
+ Script: //脚本
+'VV:=(HIGH+OPEN+LOW+CLOSE)/4;\n\
+VMA1:MA(VV,M1);\n\
+VMA2:MA(VV,M2);\n\
+VMA3:MA(VV,M3);\n\
+VMA4:MA(VV,M4);\n\
+VMA5:MA(VV,M5);'
+
+ };
+
+ return data;
+}
+
+
+JSIndexScript.prototype.AMV = function ()
+{
+ let data =
+ {
+ Name: 'AMV', Description: '成本价均线', IsMainIndex: false,
+ Args: [{ Name: 'M1', Value: 6 },{ Name: 'M2', Value: 12 },{ Name: 'M3', Value: 30 },{ Name: 'M4', Value: 72 },{ Name: 'M5', Value: 144 }],
+ Script: //脚本
+'AMOV:=VOL*(OPEN+CLOSE)/2;\n\
+AMV1:SUM(AMOV,M1)/SUM(VOL,M1);\n\
+AMV2:SUM(AMOV,M2)/SUM(VOL,M2);\n\
+AMV3:SUM(AMOV,M3)/SUM(VOL,M3);\n\
+AMV4:SUM(AMOV,M4)/SUM(VOL,M4);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.BBIBOLL = function ()
+{
+ let data =
+ {
+ Name: 'BBIBOLL', Description: '多空布林线', IsMainIndex: true,
+ Args: [{ Name: 'N', Value: 11 },{ Name: 'M', Value: 6 }],
+ Script: //脚本
+'CV:=CLOSE;\n\
+BBIBOLL:(MA(CV,3)+MA(CV,6)+MA(CV,12)+MA(CV,24))/4;\n\
+UPR:BBIBOLL+M*STD(BBIBOLL,N);\n\
+DWN:BBIBOLL-M*STD(BBIBOLL,N);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.ALLIGAT = function ()
+{
+ let data =
+ {
+ Name: 'ALLIGAT', Description: '鳄鱼线', IsMainIndex: true,
+ Args: [],
+ Script: //脚本
+'NN:=(H+L)/2;\n\
+上唇:REF(MA(NN,5),3),COLOR40FF40;\n\
+牙齿:REF(MA(NN,8),5),COLOR0000C0;\n\
+下颚:REF(MA(NN,13),8),COLORFF4040;'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.ZX = function ()
+{
+ let data =
+ {
+ Name: 'ZX', Description: '重心线', IsMainIndex: false,
+ Args: [],
+ Script: //脚本
+'AV:0.01*AMOUNT/VOL;'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.XS = function ()
+{
+ let data =
+ {
+ Name: 'XS', Description: '薛斯通道', IsMainIndex: true,
+ Args: [{ Name: 'N', Value: 13 }],
+ Script: //脚本
+'VAR2:=CLOSE*VOL;\n\
+VAR3:=EMA((EMA(VAR2,3)/EMA(VOL,3)+EMA(VAR2,6)/EMA(VOL,6)+EMA(VAR2,12)/EMA(VOL,12)+EMA(VAR2,24)/EMA(VOL,24))/4,N);\n\
+SUP:1.06*VAR3;\n\
+SDN:VAR3*0.94;\n\
+VAR4:=EMA(CLOSE,9);\n\
+LUP:EMA(VAR4*1.14,5);\n\
+LDN:EMA(VAR4*0.86,5);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.XS2 = function ()
+{
+ let data =
+ {
+ Name: 'XS2', Description: '薛斯通道II', IsMainIndex: true,
+ Args: [{ Name: 'N', Value: 102 },{ Name: 'M', Value: 7 }],
+ Script: //脚本
+'AA:=MA((2*CLOSE+HIGH+LOW)/4,5); \n\
+通道1:AA*N/100; \n\
+通道2:AA*(200-N)/100; \n\
+CC:=ABS((2*CLOSE+HIGH+LOW)/4-MA(CLOSE,20))/MA(CLOSE,20); \n\
+DD:=DMA(CLOSE,CC); \n\
+通道3:(1+M/100)*DD; \n\
+通道4:(1-M/100)*DD;'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.SG_XDT = function ()
+{
+ let data =
+ {
+ Name: 'SG-XDT', Description: '心电图(需下载日线)', IsMainIndex: false,
+ Args: [{ Name: 'P1', Value: 5 },{ Name: 'P2', Value: 10 }],
+ Script: //脚本
+'QR:CLOSE/INDEXC*1000;\n\
+MQR1:MA(QR,5);\n\
+MQR2:MA(QR,10);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.SG_SMX = function ()
+{
+ let data =
+ {
+ Name: 'SG-SMX', Description: '生命线(需下载日线)', IsMainIndex: false,
+ Args: [{ Name: 'N', Value: 50 }],
+ Script: //脚本
+'H1:=HHV(HIGH,N);\n\
+L1:=LLV(LOW,N);\n\
+H2:=HHV(INDEXH,N);\n\
+L2:=LLV(INDEXL,N);\n\
+ZY:=CLOSE/INDEXC*2000;\n\
+ZY1:EMA(ZY,3);\n\
+ZY2:EMA(ZY,17);\n\
+ZY3:EMA(ZY,34);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.SG_LB = function ()
+{
+ let data =
+ {
+ Name: 'SG-LB', Description: '量比(需下载日线)', IsMainIndex: false,
+ Args: [],
+ Script: //脚本
+'ZY2:=VOL/INDEXV*1000;\n\
+量比:ZY2;\n\
+MA5:MA(ZY2,5);\n\
+MA10:MA(ZY2,10);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.SG_PF = function ()
+{
+ let data =
+ {
+ Name: 'SG-PF', Description: '强势股评分(需下载日线)', IsMainIndex: false,
+ Args: [],
+ Script: //脚本
+'ZY1:=CLOSE/INDEXC*1000;\n\
+A1:=IF(ZY1>HHV(ZY1,3),10,0);\n\
+A2:=IF(ZY1>HHV(ZY1,5),15,0);\n\
+A3:=IF(ZY1>HHV(ZY1,10),20,0);\n\
+A4:=IF(ZY1>HHV(ZY1,2),10,0);\n\
+A5:=COUNT(ZY1>REF(ZY1,1) ,9)*5;\n\
+强势股评分:A1+A2+A3+A4+A5;'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.RAD = function ()
+{
+ let data =
+ {
+ Name: 'RAD', Description: '威力雷达(需下载日线)', IsMainIndex: false,
+ Args: [{ Name: 'D', Value: 3 },{ Name: 'S', Value: 30 },{ Name: 'M', Value: 30 }],
+ Script: //脚本
+'SM:=(OPEN+HIGH+CLOSE+LOW)/4;\n\
+SMID:=MA(SM,D);\n\
+IM:=(INDEXO+INDEXH+INDEXL+INDEXC)/4;\n\
+IMID:=MA(IM,D);\n\
+SI1:=(SMID-REF(SMID,1))/SMID;\n\
+II:=(IMID-REF(IMID,1))/IMID;\n\
+RADER1:SUM((SI1-II)*2,S)*1000;\n\
+RADERMA:SMA(RADER1,M,1);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.SHT = function ()
+{
+ let data =
+ {
+ Name: 'SHT', Description: '龙系短线', IsMainIndex: false,
+ Args: [{ Name: 'N', Value: 5 }],
+ Script: //脚本
+'VAR1:=MA((VOL-REF(VOL,1))/REF(VOL,1),5);\n\
+VAR2:=(CLOSE-MA(CLOSE,24))/MA(CLOSE,24)*100;\n\
+MY: VAR2*(1+VAR1);\n\
+SHT: MY, COLORSTICK;\n\
+SHTMA: MA(SHT,N);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.ZLJC = function ()
+{
+ let data =
+ {
+ Name: 'ZLJC', Description: '主力进出', IsMainIndex: false,
+ Args: [],
+ Script: //脚本
+'VAR1:=(CLOSE+LOW+HIGH)/3; \n\
+VAR2:=SUM(((VAR1-REF(LOW,1))-(HIGH-VAR1))*VOL/100000/(HIGH-LOW),0); \n\
+VAR3:=EMA(VAR2,1); \n\
+JCS:VAR3; \n\
+JCM:MA(VAR3,12); \n\
+JCL:MA(VAR3,26);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.ZLMM = function ()
+{
+ let data =
+ {
+ Name: 'ZLMM', Description: '主力买卖', IsMainIndex: false,
+ Args: [],
+ Script: //脚本
+'LC :=REF(CLOSE,1);\n\
+RSI2:=SMA(MAX(CLOSE-LC,0),12,1)/SMA(ABS(CLOSE-LC),12,1)*100;\n\
+RSI3:=SMA(MAX(CLOSE-LC,0),18,1)/SMA(ABS(CLOSE-LC),18,1)*100;\n\
+MMS:MA(3*RSI2-2*SMA(MAX(CLOSE-LC,0),16,1)/SMA(ABS(CLOSE-LC),16,1)*100,3);\n\
+MMM:EMA(MMS,8);\n\
+MML:MA(3*RSI3-2*SMA(MAX(CLOSE-LC,0),12,1)/SMA(ABS(CLOSE-LC),12,1)*100,5);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.SLZT = function ()
+{
+ let data =
+ {
+ Name: 'SLZT', Description: '神龙在天', IsMainIndex: false,
+ Args: [],
+ Script: //脚本
+'白龙: MA(CLOSE,125);\n\
+黄龙: 白龙+2*STD(CLOSE,170);\n\
+紫龙: 白龙-2*STD(CLOSE,145);\n\
+青龙: SAR(125,1,7), LINESTICK;\n\
+VAR2:=HHV(HIGH,70);\n\
+VAR3:=HHV(HIGH,20);\n\
+红龙: VAR2*0.83;\n\
+蓝龙: VAR3*0.91;'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.ADVOL = function ()
+{
+ let data =
+ {
+ Name: 'ADVOL', Description: '龙系离散量', IsMainIndex: false,
+ Args: [],
+ Script: //脚本
+'A:=SUM(((CLOSE-LOW)-(HIGH-CLOSE))*VOL/10000/(HIGH-LOW),0);\n\
+ADVOL:A;\n\
+MA1:MA(A,30);\n\
+MA2:MA(MA1,100);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.CYC = function ()
+{
+ let data =
+ {
+ Name: 'CYC', Description: '成本均线', IsMainIndex: true,
+ Args: [{ Name: 'P1', Value: 5 },{ Name: 'P2', Value: 13 },{ Name: 'P3', Value: 34 }],
+ Script: //脚本
+'JJJ:=IF(DYNAINFO(8)>0.01,0.01*DYNAINFO(10)/DYNAINFO(8),DYNAINFO(3));\n\
+DDD:=(DYNAINFO(5)<0.01 || DYNAINFO(6)<0.01);\n\
+JJJT:=IF(DDD,1,(JJJ<(DYNAINFO(5)+0.01) && JJJ>(DYNAINFO(6)-0.01)));\n\
+CYC1:IF(JJJT,0.01*EMA(AMOUNT,P1)/EMA(VOL,P1),EMA((HIGH+LOW+CLOSE)/3,P1));\n\
+CYC2:IF(JJJT,0.01*EMA(AMOUNT,P2)/EMA(VOL,P2),EMA((HIGH+LOW+CLOSE)/3,P2));\n\
+CYC3:IF(JJJT,0.01*EMA(AMOUNT,P3)/EMA(VOL,P3),EMA((HIGH+LOW+CLOSE)/3,P3));\n\
+CYC4:IF(JJJT,DMA(AMOUNT/(100*VOL),100*VOL/FINANCE(7)),EMA((HIGH+LOW+CLOSE)/3,120));'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.CYS = function ()
+{
+ let data =
+ {
+ Name: 'CYS', Description: '市场盈亏', IsMainIndex: false,
+ Args: [],
+ Script: //脚本
+'CYC13:EMA(AMOUNT,13)/EMA(VOL,13);\n\
+CYS:(CLOSE-CYC13)/CYC13*100;'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.CYQKL = function ()
+{
+ let data =
+ {
+ Name: 'CYQKL', Description: '博弈K线长度', IsMainIndex: false,
+ Args: [],
+ Script: //脚本
+'KL:100*(WINNER(CLOSE)-WINNER(OPEN));'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.SCR = function ()
+{
+ let data =
+ {
+ Name: 'SCR', Description: '筹码集中度', IsMainIndex: false,
+ Args: [{ Name: 'P1', Value: 90 }],
+ Script: //脚本
+'A:=P1+(100-P1)/2;\n\
+B:=(100-P1)/2;\n\
+CC:=COST(A);\n\
+DD:=COST(B);\n\
+SCR:(CC-DD)/(CC+DD)*100/2;'
+
+ };
+
+ return data;
+}
+
+
+JSIndexScript.prototype.ASR = function ()
+{
+ let data =
+ {
+ Name: 'ASR', Description: '浮筹比例', IsMainIndex: false,
+ Args: [],
+ Script: //脚本
+'ASR:(WINNER(C*1.1)-WINNER(C*0.9))/WINNER(HHV(H,0))*100;'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.SAR = function ()
+{
+ let data =
+ {
+ Name: 'SAR', Description: '抛物转向', IsMainIndex: true,
+ Args: [{ Name: 'P', Value: 10 },{ Name: 'STEP', Value: 2 },{ Name: 'MAXP', Value: 20 }],
+ Script: //脚本
+'S:SAR(P,STEP,MAXP),CIRCLEDOT;'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.TJCJL = function ()
+{
+ let data =
+ {
+ Name: '太极成交量', Description: '太极成交量', IsMainIndex: true,
+ Args: [],
+ Script: //脚本
+'总手:VOL,NODRAW;\n\
+DRAWTEXT_FIX(ISLASTBAR,0,0,0,"说明: 红色柱为吸货量,绿色为出货量,黄色为天量,蓝色为地量"),COLORGRAY;\n\
+ZZ:=IF(REF(C,1)>REF(O,1) AND O>REF(C,1)*1.014 AND CV5*1.2 AND V>V12*1.2 AND ZZ>2 AND C>H*0.975,0,VOL,3,0),COLORRED;\n\
+STICKLINE(CROSS(C6,C) AND V>V5*1.2 AND V>V12*1.2,0,VOL,3,0),COLORGREEN;\n\
+STICKLINE(VOL>MA(VOL,5)*2 AND V>V34*3 AND C][MA(VOL,5)*2 AND V>V34*3 AND C][V5*1.2 AND V>V12*1.2 AND ZZ>2 AND C>H*0.975,VOL*0.5,0,3,0),COLORRED;\n\
+STICKLINE(VOL>MA(VOL,5)*2 AND V>V34*3 AND C][V5*1.2 AND V>V12*1.2,VOL*0.5,0,3,0),COLORRED;'
+
+ };
+
+ return data;
+}
+
+/*
+ 飞龙四式-主图
+*/
+JSIndexScript.prototype.Dragon4_Main = function ()
+{
+ let data =
+ {
+ Name: '飞龙四式', Description: '飞龙四式', IsMainIndex: true,
+ Args: [{ Name: 'N1', Value: 5 }, { Name: 'N2', Value: 10 }, { Name: 'N3', Value: 50 }, { Name: 'N4', Value: 60 }],
+ Script: //脚本
+'蜻蜓点水:=EMA(CLOSE,N1),COLORGRAY;\n\
+魔界:=EMA(CLOSE,N2),COLORGREEN;\n\
+水:=EMA(CLOSE,N3),COLORRED;\n\
+DRAWKLINE(HIGH,OPEN,LOW,CLOSE);\n\
+生命线:MA(CLOSE,N4),COLORBLUE,LINETHICK2;\n\
+DRAWBAND(魔界,\'RGB(186,225,250)\',水,\'RGB(253,194,124)\');\n\
+DRAWBAND(蜻蜓点水,\'RGB(128,138,135)\',魔界,\'RGB(0,0,255)\');'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.Dragon4_Fig=function()
+{
+ let data =
+ {
+ Name: '飞龙四式', Description: '飞龙四式', IsMainIndex: false,
+ Args: [],
+ Script: //脚本
+'倍:VOL>=REF(V,1)*1.90 AND C>REF(C,1),COLORYELLOW;\n\
+低:VOL][REF(V,1),3)==3 AND COUNT(C>O,3)==3,COLORBROWN;\n\
+缩量涨:COUNT(C>REF(C,1),2)==2 AND COUNT(V][=REF(C,1),V,0,2,0),COLORRED;\n\
+STICKLINE(C][=2038 AND MONTH>=1,0,1);
+VAR2:=REF(LOW,1)*VAR1;
+VAR3:=SMA(ABS(LOW-VAR2),3,1)/SMA(MAX(LOW-VAR2,0),3,1)*100*VAR1;
+VAR4:=EMA(IF(CLOSE*1.3,VAR3*10,VAR3/10),3)*VAR1;
+VAR5:=LLV(LOW,30)*VAR1;
+VAR6:=HHV(VAR4,30)*VAR1;
+VAR7:=IF(MA(CLOSE,58),1,0)*VAR1;
+VAR8:=EMA(IF(LOW<=VAR5,(VAR4+VAR6*2)/2,0),3)/618*VAR7*VAR1;
+吸筹A:IF(VAR8>100,100,VAR8)*VAR1,COLORRED;
+吸筹B:STICKLINE(吸筹A>-150,0,吸筹A,8,0),COLORRED;
+
+散户线: 100*(HHV(HIGH,M)-CLOSE)/(HHV(HIGH,M)-LLV(LOW,M)),COLORFFFF00,LINETHICK2;
+RSV:=(CLOSE-LLV(LOW,N))/(HHV(HIGH,N)-LLV(LOW,N))*100;
+K:=SMA(RSV,3,1);
+D:=SMA(K,3,1);
+J:=3*K-2*D;
+主力线:EMA(J,5),COLORFF00FF,LINETHICK2;
+DRAWICON(CROSS(主力线,散户线),主力线,1);
+DRAWICON(CROSS(散户线,主力线),主力线,2);
+*/
+
+JSIndexScript.prototype.FundsAnalysis=function()
+{
+ let data =
+ {
+ Name: '资金分析', Description: '资金分析', IsMainIndex: false,
+ Args: [{ Name: 'M', Value: 55 }, { Name: 'N', Value: 34 }],
+ Script: //脚本
+'LC:=REF(CLOSE,1);\n\
+RSI:=((SMA(MAX((CLOSE - LC),0),3,1) / SMA(ABS((CLOSE - LC)),3,1)) * 100);\n\
+FF:=EMA(CLOSE,3);\n\
+MA15:=EMA(CLOSE,21); DRAWTEXT(CROSS(85,RSI),75,\'▼\'),COLORGREEN;\n\
+VAR1:=IF(YEAR>=2038 AND MONTH>=1,0,1);\n\
+VAR2:=REF(LOW,1)*VAR1;\n\
+VAR3:=SMA(ABS(LOW-VAR2),3,1)/SMA(MAX(LOW-VAR2,0),3,1)*100*VAR1;\n\
+VAR4:=EMA(IF(CLOSE*1.3,VAR3*10,VAR3/10),3)*VAR1;\n\
+VAR5:=LLV(LOW,30)*VAR1;\n\
+VAR6:=HHV(VAR4,30)*VAR1;\n\
+VAR7:=IF(MA(CLOSE,58),1,0)*VAR1;\n\
+VAR8:=EMA(IF(LOW<=VAR5,(VAR4+VAR6*2)/2,0),3)/618*VAR7*VAR1;\n\
+吸筹A:IF(VAR8>100,100,VAR8)*VAR1,COLORFB2F3B;\n\
+{吸筹B}STICKLINE(吸筹A>-150,0,吸筹A,8,0),COLORFB2F3B;\n\
+\n\
+散户线: 100*(HHV(HIGH,M)-CLOSE)/(HHV(HIGH,M)-LLV(LOW,M)),COLORAA89BD,LINETHICK2;\n\
+RSV:=(CLOSE-LLV(LOW,N))/(HHV(HIGH,N)-LLV(LOW,N))*100;\n\
+K:=SMA(RSV,3,1);\n\
+D:=SMA(K,3,1);\n\
+J:=3*K-2*D;\n\
+主力线:EMA(J,5),COLORF39800,LINETHICK2;\n\
+DRAWICON(CROSS(主力线,散户线),主力线,1);\n\
+DRAWICON(CROSS(散户线,主力线),主力线,2);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.MarginProportion=function()
+{
+ let data =
+ {
+ Name: '融资占比(%)', Description: '融资占比', IsMainIndex: false,
+ Condition: { Period:[CONDITION_PERIOD.KLINE_DAY_ID] },
+ Args: [],
+ Script: //脚本
+ '占比:MARGIN(2);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.Margin2=function()
+{
+ let data =
+ {
+ Name: '两融余额', Description: '融资融券余额', IsMainIndex: false,
+ Condition: { Period:[CONDITION_PERIOD.KLINE_DAY_ID] },
+ Args: [{ Name: 'N', Value: 5 }],
+ Script: //脚本
+ 'T1:MARGIN(1);\n\
+ T2:MA(MARGIN(1),N);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.Margin3=function()
+{
+ let data =
+ {
+ Name: '两融余额', Description: '融资融券余额', IsMainIndex: false,
+ Condition: { Period:[CONDITION_PERIOD.KLINE_DAY_ID] },
+ Args: [{ Name: 'N', Value: 5 }],
+ Script: //脚本
+ 'T1:=MARGIN(1);\n\
+ T2:=MA(MARGIN(1),N);\n\
+ STICKLINE(T1-T2>=0,0,T1-T2,50,T1>T2),COLORRED;\n\
+ STICKLINE(T1-T2<0,T1-T2,0,50,T1>T2),COLORGREEN;'
+ };
+
+ return data;
+}
+
+
+
+JSIndexScript.prototype.FXG_BSPoint=function()
+{
+ let data =
+ {
+ Name: '操盘BS点', Description: '操盘BS点', IsMainIndex: true,
+ Args: [],
+ Script: //脚本
+ 'MA5:MA(CLOSE,5);\n\
+ MA13:MA(CLOSE,13);\n\
+ MA21:MA(CLOSE,21);\n\
+ MA34:MA(CLOSE,34);\n\
+ {MA55:MA(CLOSE,55),COLOR0000FF;}\n\
+ {MA120:=MA(CLOSE,120),COLORFFFF00;}\n\
+ 天使:=EMA(C,2),COLOR000000;\n\
+ 魔鬼:=EMA(SLOPE(C,21)*20+C,42),COLOR000000;\n\
+ 买:=CROSS(天使,魔鬼);\n\
+ 卖:=CROSS(魔鬼,天使);\n\
+ DRAWICON(买,L*0.97,13);\n\
+ DRAWICON(卖,H*1.03,14);\n\
+ DRAWKLINE_IF(天使>=魔鬼,HIGH,CLOSE,LOW,OPEN),COLORRED;\n\
+ DRAWKLINE_IF(天使<魔鬼,HIGH,CLOSE,LOW,OPEN),COLORBLUE;\n\
+ DRAWKLINE_IF(CROSS(天使,魔鬼),HIGH,CLOSE,LOW,OPEN),COLORYELLOW;\n\
+ DRAWKLINE_IF(CROSS(魔鬼,天使),HIGH,CLOSE,LOW,OPEN),COLORBLACK;'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.FXG_INDEX=function()
+{
+ let data =
+ {
+ Name: '涨停多空线', Description: '涨停多空线', IsMainIndex: false,
+ Args: [],
+ Script: //脚本
+'做多能量线: SMA((CLOSE-LLV(LOW,9))/(HHV(HIGH,9)-LLV(LOW,9))*100,5,1)-8,COLORRED,LINETHICK3;\n\
+做空能量线: SMA((HHV(HIGH,36)-CLOSE)/(HHV(HIGH,36)-LLV(LOW,36))*100,2,1),COLORGREEN,LINETHICK3;\n\
+20,POINTDOT,COLORF00FF0;\n\
+50,POINTDOT,COLORGREEN;\n\
+80,POINTDOT,COLORLIBLUE;'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.FXG_INDEX2=function()
+{
+ let data =
+ {
+ Name: '涨停吸筹区', Description: '涨停吸筹区', IsMainIndex: false,
+ Args: [],
+ Script: //脚本
+'VAR0:=EMA(HHV(HIGH,500),21); \n\
+VAR1:=EMA(HHV(HIGH,250),21);\n\
+VAR2:=EMA(HHV(HIGH,90),21); \n\
+VAR3:=EMA(LLV(LOW,500),21); \n\
+VAR4:=EMA(LLV(LOW,250),21); \n\
+VAR5:=EMA(LLV(LOW,90),21);\n\
+\n\
+VAR6:=EMA((VAR3*0.96+VAR4*0.96+VAR5*0.96+VAR0*0.558+VAR1*0.558+VAR2*0.558)/6,21); \n\
+VAR7:=EMA((VAR3*1.25+VAR4*1.23+VAR5*1.2+VAR0*0.55+VAR1*0.55+VAR2*0.65)/6,21); \n\
+VAR8:=EMA((VAR3*1.3+VAR4*1.3+VAR5*1.3+VAR0*0.68+VAR1*0.68+VAR2*0.68)/6,21); \n\
+VAR9:=EMA((VAR6*3+VAR7*2+VAR8)/6*1.738,21); \n\
+VAR10:=REF(LOW,1); \n\
+VAR11:=SMA(ABS(LOW-VAR10),3,1)/SMA(MAX(LOW-VAR10,0),3,1)*100; \n\
+VAR12:=EMA(IFF(CLOSE*1.35<=VAR9,VAR11*10,VAR11/10),3); \n\
+VAR13:=LLV(LOW,30); \n\
+VAR14:=HHV(VAR12,30); \n\
+VAR15:=IFF(MA(CLOSE,58),1,0); \n\
+VAR16:=EMA(IFF(LOW<=VAR13,(VAR12+VAR14*2)/2,0),3)/618*VAR15;\n\
+\n\
+资金入场:IFF(VAR16>0,VAR16,0),LINETHICK,LINETHICK2, COLORFF0000; \n\
+\n\
+A1:IFF(资金入场>0,资金入场*1.2,0),STICK,LINETHICK5, COLORFF0000;\n\
+A2:IFF(资金入场>0,资金入场*0.8,0),STICK,LINETHICK5, COLORFF6600;\n\
+A3:IFF(资金入场>0,资金入场*0.6,0),STICK,LINETHICK5, COLORFF9900;\n\
+A4:IFF(资金入场>0,资金入场*0.4,0) ,STICK,LINETHICK5,COLORFFCC00;\n\
+A5:IFF(资金入场>0,资金入场*0.2,0) ,STICK,LINETHICK5,COLORFFFF00;'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.FXG_INDEX3=function()
+{
+ let data =
+ {
+ Name: '量能黄金点', Description: '量能黄金点', IsMainIndex: false,FloatPrecision:0,
+ Args: [],
+ Script: //脚本
+'A:=IFF((CLOSE>126.32),VOL,VOL); \n\
+主力:=MA(A,4),COLORRED;\n\
+游资:=MA(A,8),COLORYELLOW;\n\
+大户:=MA(A,16),COLORF0F000;\n\
+散户:=MA(A,32),COLOR00FF00;\n\
+主比:=ABS(((主力)/(主力 + 游资 + 大户 + 散户))*(100)),LINESTICK,COLORRED;\n\
+游比:=ABS(((游资)/(主力 + 游资 + 大户 + 散户))*(100)),LINESTICK,COLORYELLOW;\n\
+大比:=ABS(((大户)/(主力 + 游资 + 大户 + 散户))*(100)),LINESTICK,COLORF0F000;\n\
+散比:=ABS(((散户)/(主力 + 游资 + 大户 + 散户))*(100)),LINESTICK,COLOR00FF00;\n\
+警戒线:MA(A,180),COLORFF66FF;\n\
+STICKLINE((主力 > 0),0,主力,2.5,0),COLOR1020BB;\n\
+STICKLINE((主力 > 0),0,主力,0.7,0),COLORRED;\n\
+STICKLINE((游资 > 0),0,游资,2.5,0),COLOR009CFF;\n\
+STICKLINE((游资 > 0),0,游资,0.7,0),COLORYELLOW;\n\
+STICKLINE((大户 > 0),0,大户,2.5,0),COLORFF8800;\n\
+STICKLINE((大户 > 0),0,大户,0.7,0),COLORLIBLUE;\n\
+STICKLINE((散户 > 0),0,散户,2.5,0),COLOR00CA00;\n\
+STICKLINE((散户 > 0),0,散户,0.7,0),COLORGREEN;'
+ };
+
+ return data;
+}
+
+
+JSIndexScript.prototype.NewsNegative=function()
+{
+ let data=
+ {
+ Name: '负面新闻', Description: '负面新闻统计', IsMainIndex: false,FloatPrecision:0,
+ Args: [{ Name: 'N', Value: 5 }, { Name: 'N2', Value: 10 }],
+ Script: //脚本
+'负面:NEWS(1);\n\
+MA1:MA(负面,N);\n\
+MA2:MA(负面,N2);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.UpDownAnalyze=function()
+{
+ let data=
+ {
+ Name: '涨跌趋势', Description: '涨跌趋势', IsMainIndex: false,FloatPrecision:0,
+ Condition: { Period:[CONDITION_PERIOD.MINUTE_ID, CONDITION_PERIOD.MULTIDAY_MINUTE_ID, CONDITION_PERIOD.KLINE_DAY_ID] },
+ Args: [],
+ Script: //脚本
+"上涨家数:UPCOUNT('CNA.CI'),COLORRED;\n\
+下跌家数:DOWNCOUNT('CNA.CI'),COLORGREEN;"
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.HK2SHSZ=function()
+{
+ let data=
+ {
+ Name: '北上资金', Description: '北上资金', IsMainIndex: false,FloatPrecision:0,
+ Condition: { Period:[CONDITION_PERIOD.MINUTE_ID,CONDITION_PERIOD.MULTIDAY_MINUTE_ID,CONDITION_PERIOD.KLINE_DAY_ID] },
+ Args: [],
+ Script: //脚本
+ "净流入:HK2SHSZ(1),COLORSTICK;"
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.ShareHolder=function()
+{
+ let data=
+ {
+ Name: '股东人数', Description: '股东人数', IsMainIndex: false,FloatPrecision:0,
+ Condition: { Period:[
+ CONDITION_PERIOD.KLINE_DAY_ID,
+ CONDITION_PERIOD.KLINE_MONTH_ID,
+ CONDITION_PERIOD.KLINE_WEEK_ID,
+ CONDITION_PERIOD.KLINE_YEAR_ID] },
+ Args: [],
+ Script: //脚本
+ "人数:FINANCE(100);"
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.VOLRate=function()
+{
+ let data=
+ {
+ Name: '量比', Description: '量比', IsMainIndex: false, Condition: { Period:[CONDITION_PERIOD.MINUTE_ID, CONDITION_PERIOD.MULTIDAY_MINUTE_ID ] },
+ Args: [],
+ Script: //脚本
+ "LIANGBI:VOLR;"
+ };
+
+ return data;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+//五彩K线
+
+JSIndexScript.prototype.COLOR_KSTAR1=function()
+{
+ let data=
+ {
+ Name: '十字星', Description: '十字星', IsMainIndex: true, InstructionType:2,
+ Script: //脚本
+ 'KSTAR:CLOSE==OPEN&&HIGH>LOW;'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_KSTAR2=function()
+{
+ let data=
+ {
+ Name: '早晨之星', Description: '早晨之星', IsMainIndex: true, InstructionType:2,
+ Script: //脚本
+ 'KSTAR:(REF(CLOSE,2)/REF(OPEN,2)<0.95) && (REF(OPEN,1) < REF(CLOSE,2)) && (ABS(REF(OPEN,1)-REF(CLOSE,1))/REF(CLOSE,1)<0.03) && CLOSE/OPEN>1.05 && CLOSE>REF(CLOSE,2);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_KSTAR3=function()
+{
+ let data=
+ {
+ Name: '黄昏之星', Description: '黄昏之星', IsMainIndex: true, InstructionType:2,
+ Script: //脚本
+ 'KSTAR:REF(CLOSE,2)/REF(OPEN,2)>1.05 && REF(OPEN,1)>REF(CLOSE,2) && ABS(REF(OPEN,1)-REF(CLOSE,1))/REF(CLOSE,1)<0.03 && CLOSE/OPEN<0.95 && CLOSE][1.03;'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_K220=function()
+{
+ let data=
+ {
+ Name: '身怀六甲', Description: '身怀六甲', IsMainIndex: true, InstructionType:2,
+ Script: //脚本
+ 'KSTAR:ABS(REF(CLOSE,1)-REF(OPEN,1))/REF(CLOSE,1)>0.04&&\n\
+ ABS(CLOSE-OPEN)/CLOSE<0.005&&\n\
+ MAX(CLOSE,OPEN)MIN(REF(CLOSE,1),REF(OPEN,1));'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_K300=function()
+{
+ let data=
+ {
+ Name: '三个白武士', Description: '三个白武士', IsMainIndex: true, InstructionType:2,
+ Script: //脚本
+ 'KSTAR:UPNDAY(CLOSE,3)&&NDAY(CLOSE,OPEN,3);'
+ };
+
+ return data;
+}
+
+
+JSIndexScript.prototype.COLOR_K310=function()
+{
+ let data=
+ {
+ Name: '三只乌鸦', Description: '三只乌鸦', IsMainIndex: true, InstructionType:2,
+ Script: //脚本
+ 'KSTAR:DOWNNDAY(CLOSE,3)&&NDAY(OPEN,CLOSE,3);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_K380=function()
+{
+ let data=
+ {
+ Name: '光头阳线', Description: '光头阳线', IsMainIndex: true, InstructionType:2,
+ Script: //脚本
+ 'KSTAR:HIGH==CLOSE&&HIGH>LOW;'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_K390=function()
+{
+ let data=
+ {
+ Name: '光脚阴线', Description: '光脚阴线', IsMainIndex: true, InstructionType:2,
+ Script: //脚本
+ 'KSTAR:LOW==CLOSE&&HIGH>LOW;'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_K134=function()
+{
+ let data=
+ {
+ Name: '垂死十字', Description: '垂死十字', IsMainIndex: true, InstructionType:2,
+ Script: //脚本
+ 'KSTAR:CLOSE==OPEN&&CLOSE==LOW&&CLOSE1.05&&CLOSE>REF(CLOSE,2);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_K150=function()
+{
+ let data=
+ {
+ Name: '黄昏十字星', Description: '黄昏十字星', IsMainIndex: true, InstructionType:2,
+ Script: //脚本
+'KSTAR:REF(CLOSE,2)/REF(OPEN,2)>1.05&&\n\
+REF(OPEN,1)>REF(CLOSE,2)&&\n\
+REF(OPEN,1)=REF(CLOSE,1)&&\n\
+CLOSE/OPEN<0.95&&CLOSE][3*(MAX(OPEN,CLOSE)-LOW)&&\n\
+CLOSE>MA(CLOSE,5);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_K165=function()
+{
+ let data=
+ {
+ Name: '倒转锤头', Description: '倒转锤头', IsMainIndex: true, InstructionType:2,
+ Script: //脚本
+'KSTAR:MIN(OPEN,CLOSE)==LOW&&\n\
+HIGH-LOW>3*(MAX(OPEN,CLOSE)-LOW)&&\n\
+CLOSE3*(HIGH-MIN(OPEN,CLOSE))&&\n\
+CLOSE3*(HIGH-MIN(OPEN,CLOSE))&&\n\
+CLOSE>MA(CLOSE,5);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_K190=function()
+{
+ let data=
+ {
+ Name: '穿头破脚', Description: '穿头破脚', IsMainIndex: true, InstructionType:2,
+ Script: //脚本
+'OUT:(REF(CLOSE,1)/REF(OPEN,1)>1.03&&\n\
+CLOSE/OPEN<0.96&&\n\
+CLOSE][REF(CLOSE,1))||\n\
+(REF(CLOSE,1)/REF(OPEN,1)<0.97&&\n\
+CLOSE/OPEN>1.04&&\n\
+CLOSE>REF(OPEN,1)&&OPEN][REF(VOL,1)||VOL>(CAPITAL*0.1);\n\
+BB:=OPEN>=(REF(HIGH,1))&&REF(HIGH,1)>(REF(HIGH,2)*1.06);\n\
+CC:=CLOSE>(REF(CLOSE,1))-(REF(CLOSE,1)*0.01);\n\
+DD:=CLOSE<(HIGH*0.965) && HIGH>(OPEN*1.05);\n\
+EE:=LOW(REF(CLOSE,1)*1.06);\n\
+FF:=(HIGH-(MAX(OPEN,CLOSE)))/2>(MIN(OPEN,CLOSE))-LOW;\n\
+GG:=(ABS(OPEN-CLOSE))/2<(MIN(OPEN,CLOSE)-LOW);\n\
+SWORDO:AA&&BB&&CC&&DD&&EE&&FF&&GG;'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_CSFR=function()
+{
+ let data=
+ {
+ Name: '出水芙蓉', Description: '出水芙蓉', IsMainIndex: true, InstructionType:2,
+ Script: //脚本
+'A:=CLOSE>OPEN;\n\
+B:=A&&CLOSE>MA(CLOSE,S)&&CLOSE>MA(CLOSE,M)&&CLOSE>MA(CLOSE,LL);\n\
+CC:=B&&OPEN0.0618*CLOSE;'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_WYGD=function()
+{
+ let data=
+ {
+ Name: '乌云盖顶', Description: '乌云盖顶', IsMainIndex: true, InstructionType:2,
+ Script: //脚本
+'VAR1:BACKSET( \n\
+REF(CLOSE,1)/REF(OPEN,1)>1.03 AND \n\
+CLOSE/OPEN<0.97 AND \n\
+OPEN>REF(CLOSE,1) AND CLOSE][1.03 AND \n\
+OPEN][REF(CLOSE,1), 3);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_SZTAI=function()
+{
+ let data=
+ {
+ Name: '十字胎', Description: '十字胎', IsMainIndex: true, InstructionType:2,
+ Script: //脚本
+'VAR1:BACKSET( ABS(REF(CLOSE,1)-REF(OPEN,1))/REF(CLOSE,1) > 0.04 AND \n\
+CLOSE==OPEN AND CLOSE < MAX(REF(CLOSE,1),REF(OPEN,1)) AND \n\
+CLOSE > MIN(REF(CLOSE,1),REF(OPEN,1)), 2);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_PINGDING=function()
+{
+ let data=
+ {
+ Name: '平顶', Description: '平顶', IsMainIndex: true, InstructionType:2,
+ Script: //脚本
+'VAR1:BACKSET(ABS(HIGH-REF(HIGH,1))/HIGH<0.001,2);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_PINGDI=function()
+{
+ let data=
+ {
+ Name: '平底', Description: '平底', IsMainIndex: true, InstructionType:2,
+ Script: //脚本
+'VAR1:BACKSET((ABS(LOW-REF(LOW,1))/LOW<0.001 AND \n\
+ABS(REF(LOW,1)-REF(LOW,2))/REF(LOW,1)<=0.001),2);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_DAYANZHU=function()
+{
+ let data=
+ {
+ Name: '大阳烛', Description: '大阳烛', IsMainIndex: true, InstructionType:2,
+ Script: //脚本
+'VAR1:CLOSE/OPEN>1.05 AND HIGH/LOW < CLOSE/OPEN+0.018;'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_DAYINGZHU=function()
+{
+ let data=
+ {
+ Name: '大阴烛', Description: '大阴烛', IsMainIndex: true, InstructionType:2,
+ Script: //脚本
+'VAR1:OPEN/CLOSE > 1.05 AND HIGH/LOW < OPEN/CLOSE+0.018;'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_HYFG=function()
+{
+ let data=
+ {
+ Name: '好友反攻', Description: '好友反攻', IsMainIndex: true, InstructionType:2,
+ Script: //脚本
+'VAR1:BACKSET( (REF(CLOSE,1)][OPEN AND ABS(CLOSE-REF(CLOSE,1))/CLOSE<0.002),2);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_TKQK=function()
+{
+ let data=
+ {
+ Name: '跳空缺口', Description: '跳空缺口', IsMainIndex: true, InstructionType:2,
+ Script: //脚本
+'VAR1:BACKSET( HIGH][REF(HIGH,1),2);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_SFWY=function()
+{
+ let data=
+ {
+ Name: '双飞乌鸦', Description: '双飞乌鸦', IsMainIndex: true, InstructionType:2,
+ Script: //脚本
+'VAR1:BACKSET( REF(CLOSE,1)][1.03 AND \n\
+REF(CLOSE,3)][REF(HIGH,3) AND \n\
+REF(HIGH,4)>REF(HIGH,2) AND \n\
+REF(HIGH,4)>REF(HIGH,1) AND \n\
+CLOSE/OPEN>1.03 AND \n\
+CLOSE>REF(CLOSE,4), 5);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_XDSBQ=function()
+{
+ let data=
+ {
+ Name: '下跌三部曲', Description: '下跌三部曲', IsMainIndex: true, InstructionType:2,
+ Script: //脚本
+'VAR1:BACKSET( \n\
+REF(CLOSE,4)/REF(OPEN,4)<0.97 AND \n\
+REF(CLOSE,3)>REF(OPEN,3) AND \n\
+REF(CLOSE,2)>REF(OPEN,2) AND \n\
+REF(CLOSE,1)>REF(OPEN,1) AND \n\
+REF(LOW,4)][REF(HIGH,3) AND \n\
+REF(HIGH,4)>REF(HIGH,2) AND \n\
+REF(HIGH,4)>REF(HIGH,1) AND \n\
+CLOSE/OPEN<0.97 AND \n\
+CLOSE][0.667;'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_CHSY=function()
+{
+ let data=
+ {
+ Name: '长上影', Description: '长上影', IsMainIndex: true, InstructionType:2,
+ Script: //脚本
+'VAR2:(HIGH-MAX(CLOSE,OPEN))/(HIGH-LOW)>0.667,COLORBLUE;'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.COLOR_FENLI=function()
+{
+ let data=
+ {
+ Name: '分离', Description: '分离', IsMainIndex: true, InstructionType:2,
+ Script: //脚本
+'VAR1:BACKSET( OPEN==REF(OPEN,1) AND (CLOSE-OPEN)*(REF(CLOSE,1)-REF(OPEN,1))<0,2);'
+ };
+
+ return data;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//交易系统
+
+JSIndexScript.prototype.TRADE_BIAS = function ()
+{
+ let data =
+ {
+ Name: 'BIAS', Description: '乖离率专家系统', IsMainIndex: true, InstructionType:1,
+ Args: [{ Name: 'N', Value: 12 }, { Name: 'LL', Value: 6 },{ Name: 'LH', Value: 6 }],
+ Script: //脚本
+'BIAS:=(CLOSE-MA(CLOSE,N))/MA(CLOSE,N)*100;\n\
+ENTERLONG:CROSS(-LL,BIAS);\n\
+EXITLONG:CROSS(BIAS,LH);'
+
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.TRADE_CCI = function ()
+{
+ let data =
+ {
+ Name: 'CCI', Description: 'CCI专家系统', IsMainIndex: true, InstructionType:1,
+ Args: [{ Name: 'N', Value: 14 }],
+ Script: //脚本
+'TYP:=(HIGH+LOW+CLOSE)/3;\n\
+CCI:=(TYP-MA(TYP,N))/(0.015*AVEDEV(TYP,N));\n\
+INDEX:=CCI;\n\
+ENTERLONG:CROSS(INDEX,-100);\n\
+EXITLONG:CROSS(100,INDEX);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.TRADE_DMI = function ()
+{
+ let data =
+ {
+ Name: 'DMI', Description: '趋向专家系统', IsMainIndex: true, InstructionType:1,
+ Args: [{ Name: 'N', Value: 14 }],
+ Script: //脚本
+'MTR:=SUM(MAX(MAX(HIGH-LOW,ABS(HIGH-REF(CLOSE,1))),ABS(LOW-REF(CLOSE,1))),N);\n\
+HD :=HIGH-REF(HIGH,1);\n\
+LD :=REF(LOW,1)-LOW;\n\
+PDM:=SUM(IF(HD>0&&HD>LD,HD,0),N);\n\
+MDM:=SUM(IF(LD>0&&LD>HD,LD,0),N);\n\
+PDI:=PDM*100/MTR;\n\
+MDI:=MDM*100/MTR;\n\
+ENTERLONG:CROSS(PDI,MDI);\n\
+EXITLONG:CROSS(MDI,PDI);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.TRADE_KD = function ()
+{
+ let data =
+ {
+ Name: 'KD', Description: 'KD指标专家系统', IsMainIndex: true, InstructionType:1,
+ Args: [{ Name: 'N', Value: 9 },{ Name: 'M1', Value: 3 },{ Name: 'M2', Value: 3 }],
+ Script: //脚本
+'WRSV:=(CLOSE-LLV(LOW,N))/(HHV(HIGH,N)-LLV(LOW,N))*100;\n\
+WK:=SMA(WRSV,M1,1);\n\
+D:=SMA(WK,M2,1);\n\
+ENTERLONG:CROSS(WK,D)&&WK<20;\n\
+EXITLONG:CROSS(D,WK)&&WK>80;'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.TRADE_BOLL = function ()
+{
+ let data =
+ {
+ Name: 'BOLL', Description: '布林带专家系统', IsMainIndex: true, InstructionType:1,
+ Args: [{ Name: 'N', Value: 20 }],
+ Script: //脚本
+'MID :=MA(CLOSE,N);\n\
+UPPER:=MID+2*STD(CLOSE,N);\n\
+LOWER:=MID-2*STD(CLOSE,N);\n\
+ENTERLONG:CROSS(CLOSE,LOWER);\n\
+EXITLONG:CROSS(CLOSE,UPPER);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.TRADE_KDJ = function ()
+{
+ let data =
+ {
+ Name: 'KDJ', Description: 'KDJ专家系统', IsMainIndex: true, InstructionType:1,
+ Args: [{ Name: 'N', Value: 9 },{ Name: 'M1', Value: 3 }],
+ Script: //脚本
+'RSV:=(CLOSE-LLV(LOW,N))/(HHV(HIGH,N)-LLV(LOW,N))*100;\n\
+K:=SMA(RSV,M1,1);\n\
+D:=SMA(K,M1,1);\n\
+J:=3*K-2*D;\n\
+ENTERLONG:CROSS(J,0);\n\
+EXITLONG:CROSS(100,J);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.TRADE_MA = function ()
+{
+ let data =
+ {
+ Name: 'MA', Description: '均线专家系统', IsMainIndex: true, InstructionType:1,
+ Args: [{ Name: 'SHORT', Value: 5 },{ Name: 'LONG', Value: 20 }],
+ Script: //脚本
+'ENTERLONG:CROSS(MA(CLOSE,SHORT),MA(CLOSE,LONG));\n\
+EXITLONG:CROSS(MA(CLOSE,LONG),MA(CLOSE,SHORT));'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.TRADE_MACD = function ()
+{
+ let data =
+ {
+ Name: 'MACD', Description: 'MACD专家系统', IsMainIndex: true, InstructionType:1,
+ Args: [{ Name: 'LONG', Value: 26 }, { Name: 'SHORT', Value: 12 }, { Name: 'M', Value: 9 }],
+ Script: //脚本
+'DIFF:=EMA(CLOSE,SHORT) - EMA(CLOSE,LONG);\n\
+DEA := EMA(DIFF,M);\n\
+MACD := 2*(DIFF-DEA);\n\
+ENTERLONG:CROSS(MACD,0);\n\
+EXITLONG:CROSS(0,MACD);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.TRADE_MTM = function ()
+{
+ let data =
+ {
+ Name: 'MTM', Description: '动力指标专家系统', IsMainIndex: true, InstructionType:1,
+ Args: [{ Name: 'N', Value: 6 }],
+ Script: //脚本
+'WMTM:=C-REF(C,N);\n\
+ENTERLONG:CROSS(WMTM,0);\n\
+EXITLONG:CROSS(0,WMTM);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.TRADE_PSY = function ()
+{
+ let data =
+ {
+ Name: 'PSY', Description: 'PSY心理线专家系统', IsMainIndex: true, InstructionType:1,
+ Args: [{ Name: 'N', Value: 12 },{ Name: 'LL', Value: 10 },{ Name: 'LH', Value: 85 }],
+ Script: //脚本
+'MYPSY:=COUNT(CLOSE>REF(CLOSE,1),N)/N*100;\n\
+ENTERLONG:CROSS(LL,MYPSY);\n\
+EXITLONG:CROSS(MYPSY,LH);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.TRADE_ROC = function ()
+{
+ let data =
+ {
+ Name: 'ROC', Description: '变动速率专家系统', IsMainIndex: true, InstructionType:1,
+ Args: [{ Name: 'N', Value: 12 },{ Name: 'M', Value: 6 }],
+ Script: //脚本
+'WROC:=MA(100*(CLOSE-REF(CLOSE,N))/REF(CLOSE,N),M);\n\
+ENTERLONG:CROSS(WROC,0);\n\
+EXITLONG:CROSS(0,WROC);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.TRADE_RSI = function ()
+{
+ let data =
+ {
+ Name: 'RSI', Description: '相对强弱专家系统', IsMainIndex: true, InstructionType:1,
+ Args: [{ Name: 'N', Value: 6 },{ Name: 'LL', Value: 20 },{ Name: 'LH', Value: 80 }],
+ Script: //脚本
+'LC:=REF(CLOSE,1);\n\
+WRSI:=SMA(MAX(CLOSE-LC,0),N,1)/SMA(ABS(CLOSE-LC),N,1)*100;\n\
+ENTERLONG:CROSS(WRSI,LL);\n\
+EXITLONG:CROSS(LH,WRSI);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.TRADE_VR = function ()
+{
+ let data =
+ {
+ Name: 'VR', Description: 'VR容量比率专家系统', IsMainIndex: true, InstructionType:1,
+ Args: [{ Name: 'N', Value: 26 },{ Name: 'LL', Value: 70 },{ Name: 'LH', Value: 250 }],
+ Script: //脚本
+'WVR := SUM((IF(CLOSE>OPEN,VOL,0)+IF(CLOSE=OPEN,VOL/2,0)),N)/SUM((IF(CLOSE REF(VAR5, 1), VAR5,0), COLORRED, NODRAW;\n\
+洗盘: IF(VAR5 < REF(VAR5, 1), VAR5,0), COLORYELLOW, NODRAW;\n\
+STICKLINE(VAR5> REF(VAR5, 1),0, VAR5, 20, 0), COLORRED;\n\
+STICKLINE(VAR5 < REF(VAR5, 1), 0, VAR5, 20, 0), COLORYELLOW;'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.Zealink_Index2 = function ()
+{
+ let data =
+ {
+ Name: '牛熊区间', Description: '牛熊区间', IsMainIndex: false,YSpecificMaxMin:{Max:100,Min:1,Count:4},YSplitScale:[1,50,100],
+ Args: [],
+ Script: //脚本
+'短高H:=(20*H+19*REF(H,1)+18*REF(H,2)+17*REF(H,3)+16*REF(H,4)+15*REF(H,5)+14*REF(H,6)\n\
++ 13 * REF(H, 7) + 12 * REF(H, 8) + 11 * REF(H, 9) + 10 * REF(H, 10) + 9 * REF(H, 11) + 8 * REF(H, 12)\n\
++ 7 * REF(H, 13) + 6 * REF(H, 14) + 5 * REF(H, 15) + 4 * REF(H, 16) + 3 * REF(H, 17) + 2 * REF(H, 18) +\n\
+REF(H, 20))/ 210, COLORBLUE, LINETHICK1;\n\
+短低L:= (20 * L + 19 * REF(L, 1) + 18 * REF(L, 2) + 17 * REF(L, 3) + 16 * REF(L, 4) + 15 * REF(L, 5) + 14 * REF(L, 6)\n\
++ 13 * REF(L, 7) + 12 * REF(L, 8) + 11 * REF(L, 9) + 10 * REF(L, 10) + 9 * REF(L, 11) + 8 * REF(L, 12)\n\
++ 7 * REF(L, 13) + 6 * REF(L, 14) + 5 * REF(L, 15) + 4 * REF(L, 16) + 3 * REF(L, 17) + 2 * REF(L, 18) +\n\
+REF(L, 20)) / 210, COLORBLUE, LINETHICK1;\n\
+D90H:= EMA(短高H, 90), COLORRED, LINETHICK1;\n\
+D90L:= EMA(短低L, 90), COLORRED, LINETHICK1;\n\
+D90差:= D90H - D90L;\n\
+D90顶:= D90H + D90差 * 2, COLORRED, LINETHICK1;\n\
+D90底:= D90L - D90差 * 2, COLORRED, LINETHICK1;\n\
+高0:= (EMA(EMA(H, 25), 25) - EMA(EMA(L, 25), 25)) * 1 + EMA(EMA(H, 25), 25), LINETHICK1, COLORWHITE;\n\
+低0:= EMA(EMA(L, 25), 25) - (EMA(EMA(H, 25), 25) - EMA(EMA(L, 25), 25)) * 1, LINETHICK1, COLORWHITE;\n\
+多头定位:= 低0 >= D90底 AND 高0 >= D90顶;\n\
+空头定位:= 高0 <= D90顶 AND 低0 <= D90底;\n\
+震荡定位:= 低0 >= D90底 AND 高0 <= D90顶;\n\
+牛市: IF(多头定位 == 1, 100, 1), COLORRED, NODRAW;\n\
+熊市: IF(空头定位 == 1, 100, 1), COLORGREEN, NODRAW;\n\
+震荡: IF(震荡定位 == 1, 100, 1), COLORGRAY, NODRAW;\n\
+STICKLINE(多头定位 == 1, 100, 1, 100, 0), COLORRED;\n\
+STICKLINE(空头定位 == 1, 100, 1, 100, 0), COLORGREEN;\n\
+STICKLINE(震荡定位 == 1, 100, 1, 100, 0), COLORGRAY;'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.Zealink_Index3 = function ()
+{
+ let data =
+ {
+ Name: '持仓信号', Description: '持仓信号', IsMainIndex: true,
+ Args: [],
+ Script: //脚本
+'买线:=EMA(C,2);\n\
+卖线:=EMA(SLOPE(C,30)*5+C,20); \n\
+BU:=CROSS(买线,卖线);\n\
+SEL:=CROSS(卖线,买线);\n\
+\n\
+STICKLINE(买线>=卖线 AND CLOSE>OPEN,LOW,HIGH,0,1),COLORRED;\n\
+STICKLINE(买线>=卖线 AND CLOSE=卖线 AND CLOSE>OPEN,CLOSE,OPEN,50,1),COLORRED;\n\
+STICKLINE(买线>=卖线 AND CLOSEOPEN,LOW,HIGH,0,1),COLORGREEN;\n\
+STICKLINE(买线<卖线 AND CLOSEOPEN,CLOSE,OPEN,50,1),COLORGREEN;\n\
+\n\
+HHJSJDA:=(3*CLOSE+OPEN+LOW+HIGH)/6;\n\
+HHJSJDB:(19*HHJSJDA+19*REF(HHJSJDA,1)+18*REF(HHJSJDA,2)+17*REF(HHJSJDA,3)+16*REF(HHJSJDA,4)+15*REF(HHJSJDA,5)+14*REF(HHJSJDA,6)\n\
++13*REF(HHJSJDA,7)+12*REF(HHJSJDA,8)+11*REF(HHJSJDA,9)+10*REF(HHJSJDA,10)+9*REF(HHJSJDA,11)+8*REF(HHJSJDA,12)+7*REF(HHJSJDA,13)+6*REF(HHJSJDA,14)+5*REF(HHJSJDA,15)+4*REF(HHJSJDA,16)+3*REF(HHJSJDA,17)+2*REF\n\
+(HHJSJDA,20)+REF(HHJSJDA,19))/210,COLORYELLOW;\n\
+HHJSJDC:MA(HHJSJDB,5),COLORRED;\n\
+\n\
+SVAR11:=HHV(HIGH,34);\n\
+SVAR14:=CLOSE-REF(CLOSE,1);\n\
+SVAR15:=MAX(SVAR14,0);\n\
+SVAR16:=ABS(SVAR14);\n\
+SVAR17:=SMA(SVAR15,7,1)/SMA(SVAR16,7,1)*100;\n\
+SVAR18:=SMA(SVAR15,13,1)/SMA(SVAR16,13,1)*100;\n\
+SVAR19:=BARSCOUNT(CLOSE);\n\
+SVAR20:=SMA(MAX(SVAR14,0),6,1)/SMA(ABS(SVAR14),6,1)*100;\n\
+SVAR21:=(-200)*(HHV(HIGH,60)-CLOSE)/(HHV(HIGH,60)-LLV(LOW,60))+100;\n\
+SVAR1A:=(CLOSE-LLV(LOW,15))/(HHV(HIGH,15)-LLV(LOW,15))*100;\n\
+SVAR1B:=SMA((SMA(SVAR1A,4,1)-50)*2,3,1);\n\
+SVAR1C:=(INDEXC-LLV(INDEXL,14))/(HHV(INDEXH,14)-LLV(INDEXL,14))*100;\n\
+SVAR1D:=SMA(SVAR1C,4,1);\n\
+SVAR1E:=SMA(SVAR1D,3,1);\n\
+SVAR1F:=(HHV(HIGH,30)-CLOSE)/CLOSE*100;\n\
+SVAR22:=SVAR20<=25 AND SVAR21<-95 AND SVAR1F>20 AND SVAR1B<-30 AND SVAR1E<30 AND SVAR11-CLOSE>=-0.25 AND SVAR17<22 AND SVAR18<28 AND SVAR19>50;\n\
+BUY3:=CROSS(SVAR22,0.5) AND COUNT(SVAR22==1,10)==1;\n\
+\n\
+SVARF:=LOW*0.9;\n\
+SVAR10X:=100-3*SMA((OPEN-LLV(LOW,75))/(HHV(HIGH,75)-LLV(LOW,75))*100,20,1)+2*SMA(SMA((OPEN-LLV(LOW,75))/(HHV(HIGH,75)-LLV(LOW,75))*100,20,1),15,1);\n\
+SVAR11X:=SVARF][REF(VOL,1) AND CLOSE>REF(CLOSE,1);\n\
+BUY2:=SVAR11X AND COUNT(SVAR11X,30)==1;\n\
+\n\
+VAR1:=(CLOSE+HIGH+LOW+OPEN)/4;\n\
+VAR2:=SUMBARS(VOL,CAPITAL);\n\
+VAR3:=HHV(VAR1,VAR2);\n\
+VAR4:=LLV(VAR1,VAR2);\n\
+VAR5:=(2*VAR1-VAR4-REF(VAR4,1))/(VAR3-VAR4);\n\
+VAR6:=(VAR1-VAR4)/(VAR3-VAR4);\n\
+VAR7:=IF(VAR1<=VAR4,VAR5*60,VAR6*60);\n\
+VAR8:=600*(EMA(CLOSE,3)-EMA(LOW,30))/EMA(LOW,30);\n\
+VAR9:=EMA(VAR8,7);\n\
+VARC:=HHV(HIGH,9)-LLV(LOW,9);\n\
+VARD:=HHV(HIGH,9)-CLOSE;\n\
+VARE:=CLOSE-LLV(LOW,9);\n\
+VARF:=VARD/VARC*100-70;\n\
+VAR10:=(CLOSE-LLV(LOW,60))/(HHV(HIGH,60)-LLV(LOW,60))*100;\n\
+VAR11:=(2*CLOSE+HIGH+LOW)/4;\n\
+VAR12:=SMA(VARE/VARC*100,3,1);\n\
+VAR13:=LLV(LOW,34);\n\
+VAR14:=SMA(VAR12,3,1)-SMA(VARF,9,1);\n\
+VAR15:=IF(VAR14>100,VAR14-100,0);\n\
+VAR16:=HHV(HIGH,34);\n\
+VAR17:=EMA((VAR11-VAR13)/(VAR16-VAR13)*100,8);\n\
+VAR18:=EMA(VAR17,5);\n\
+BUY:=STICKLINE(VAR17-VAR18>0,VAR17,VAR18,8,1),COLORRED;\n\
+SELL:=STICKLINE(VAR17-VAR18<0,VAR17,VAR18,8,1),COLORGREEN;\n\
+BUY1:=VAR17>VAR18 AND REF(VAR17,1)][REF(VAR18,1);\n\
+\n\
+短高H:=(20*H+19*REF(H,1)+18*REF(H,2)+17*REF(H,3)+16*REF(H,4)+15*REF(H,5)+14*REF(H,6)\n\
++13*REF(H,7)+12*REF(H,8)+11*REF(H,9)+10*REF(H,10)+9*REF(H,11)+8*REF(H,12)\n\
++7*REF(H,13)+6*REF(H,14)+5*REF(H,15)+4*REF(H,16)+3*REF(H,17)+2*REF(H,18)+\n\
+REF(H,20))/210,COLORBLUE,LINETHICK1;\n\
+短低L:=(20*L+19*REF(L,1)+18*REF(L,2)+17*REF(L,3)+16*REF(L,4)+15*REF(L,5)+14*REF(L,6)\n\
++13*REF(L,7)+12*REF(L,8)+11*REF(L,9)+10*REF(L,10)+9*REF(L,11)+8*REF(L,12)\n\
++7*REF(L,13)+6*REF(L,14)+5*REF(L,15)+4*REF(L,16)+3*REF(L,17)+2*REF(L,18)+\n\
+REF(L,20))/210,COLORBLUE,LINETHICK1;\n\
+D90H:=EMA(短高H,90),COLORRED,LINETHICK1;\n\
+D90L:=EMA(短低L,90),COLORRED,LINETHICK1;\n\
+D90差:=D90H-D90L;\n\
+D90顶:=D90H+D90差*2,COLORRED,LINETHICK1;\n\
+D90底:=D90L-D90差*2,COLORRED,LINETHICK1;\n\
+高0:=(EMA(EMA(H,25),25)-EMA(EMA(L,25),25))*1+EMA(EMA(H,25),25),LINETHICK1,COLORWHITE;\n\
+低0:=EMA(EMA(L,25),25)-(EMA(EMA(H,25),25)-EMA(EMA(L,25),25))*1,LINETHICK1,COLORWHITE;\n\
+多头定位:=低0>=D90底 AND 高0>=D90顶;\n\
+空头定位:=高0<=D90顶 AND 低0<=D90底;\n\
+震荡定位:=低0>=D90底 AND 高0<=D90顶;\n\
+\n\
+牛市:=多头定位==1;\n\
+熊市:=空头定位==1;\n\
+震荡:=震荡定位==1;\n\
+\n\
+非牛市:=熊市 OR 震荡;\n\
+非熊市:=牛市 OR 震荡;\n\
+\n\
+BUY11:=BUY1 AND 非熊市;\n\
+SELL11:=SELL1 AND 震荡定位==0;\n\
+\n\
+BUY111:=BUY11 AND COUNT(BUY11,10)<2;\n\
+BUY0:=BUY111 AND COUNT(BUY111,21)==1;\n\
+SELL111:=SELL11 AND COUNT(SELL11,10)<2;\n\
+SELL0:=SELL111 AND COUNT(SELL111,10)==1;\n\
+\n\
+XK1:=EMA(100*(CLOSE-LLV(LOW,34))/(HHV(HIGH,34)-LLV(LOW,34)),3)/4;\n\
+上穿:=REF(XK1,1)<5 AND XK1>=5;\n\
+BUY4:=上穿 AND COUNT(XK1<2,12)<1;\n\
+\n\
+SELL2:=REF(XK1,1)<=22.5 AND XK1>22.5 AND COUNT(REF(XK1,1)>=22.5 AND XK1<22.5,5)>0;\n\
+SELL3:=REF(XK1,1)>=21.5 AND XK1<21.5 AND COUNT(REF(XK1,1)>=22.5 AND XK1<22.5,12)>1;\n\
+SELL4:=SELL2 OR SELL3 AND COUNT((SELL2 OR SELL3)==1,5)==1;\n\
+\n\
+SUPERDRAWTEXT(BUY0,L,"机会",2,10),COLORRED;\n\
+SUPERDRAWTEXT(SELL0,H,"风险",1,10),COLORGREEN;\n\
+SUPERDRAWTEXT(BUY2,L,"机会",2,10),COLORRED;\n\
+SUPERDRAWTEXT(BUY4,L,"机会",2,10),COLORRED;\n\
+SUPERDRAWTEXT(SELL4,H,"风险",1,10),COLORGREEN;'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.Zealink_Index4 = function ()
+{
+ let data =
+ {
+ Name: '股东实际增减持', Description: '股东实际增减持', IsMainIndex: false, FloatPrecision:0,
+ Args: [],
+ Script: //脚本
+'增持:NEWS(4),NODRAW,COLORRED;\n\
+减持:NEWS(5),NODRAW,COLORGREEN;\n\
+STICKLINE(增持>0,0,增持,1,0),COLORRED;\n\
+STICKLINE(减持<0,0,减持,1,0),COLORGREEN;'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.Zealink_Index5 = function ()
+{
+ let data =
+ {
+ Name: '大宗交易', Description: '大宗交易', IsMainIndex: false, FloatPrecision: 0,
+ Args: [],
+ Script: //脚本
+ '交易次数:NEWS(7);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.Zealink_Index6 = function ()
+{
+ let data =
+ {
+ Name: '信托持股', Description: '信托持股', IsMainIndex: false, FloatPrecision: 0,
+ Args: [],
+ Script: //脚本
+ '家数:NEWS(6);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.Zealink_Index7 = function ()
+{
+ let data =
+ {
+ Name: '官网新闻', Description: '官网新闻', IsMainIndex: false, FloatPrecision: 0,
+ Args: [],
+ Script: //脚本
+ '个数:NEWS(8);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.Zealink_Index8 = function ()
+{
+ let data =
+ {
+ Name: '高管要闻', Description: '高管要闻', IsMainIndex: false, FloatPrecision: 0,
+ Args: [],
+ Script: //脚本
+ '个数:NEWS(9);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.Zealink_Index9 = function ()
+{
+ let data =
+ {
+ Name: '股权质押', Description: '股权质押', IsMainIndex: false, FloatPrecision: 0,
+ Args: [],
+ Script: //脚本
+ '次数:NEWS(10);'
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.Zealink_Index10 = function ()
+{
+ let data =
+ {
+ Name: '操盘BS点', Description: '操盘BS点', IsMainIndex: true, FloatPrecision: 0,
+ Args: [],
+ Script: //脚本
+"JJ:=(CLOSE+HIGH+LOW)/3; \n\
+A:=EMA(JJ,10); \n\
+B:=REF(A,1);\n\
+M1:=EMA(CLOSE,3);\n\
+M2:=EMA(CLOSE,8); \n\
+M3:=EMA(M2,13); \n\
+M4:=EMA(M2,55); \n\
+B1:=A>B AND REF(A,1)][REF(B,1);\n\
+INDEXCLOSE:INDEXC,EXDATA;\n\
+INDEXOPEN:INDEXO,EXDATA;\n\
+DRAWICON(REF(B1,1),L*0.97,13);\n\
+DRAWICON(REF(S1,1),H*1.03,14);"
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.Zealink_Index11 = function ()
+{
+ let data =
+ {
+ Name: '操盘BS点', Description: '操盘BS点', IsMainIndex: true, FloatPrecision: 0,
+ Args: [],
+ Script: //脚本
+"JJ:=(CLOSE+HIGH+LOW)/3;\n\
+A:=EMA(JJ,10);\n\
+B:=REF(A,1);\n\
+M1:=EMA(CLOSE,3);\n\
+M2:=EMA(CLOSE,8); \n\
+M3:=EMA(M2,13);\n\
+M4:=EMA(M2,55);\n\
+持股区域:=STICKLINE(A>B,A,B,2,0),COLORYELLOW; \n\
+持币区域:=STICKLINE(A100,VR14-100,0);\n\
+VR16:=HHV(H,34);\n\
+VR17:=EMA((VR11-VR13)/(VR16-VR13)*100,8);\n\
+VR18:=EMA(VR17,5);\n\
+\n\
+B1:=A>B AND REF(A,1)][REF(B,1);\n\
+\n\
+B9:=BARSLAST(REF(B1,1) AND (REF(VR17>VR18,1) OR MIN(VR17,VR18)>REF(MAX(VR17,VR18),1)));\n\
+S9:=BARSLAST(REF(S1,1) AND (REF(VR17VR18,1) OR MIN(VR17,VR18)>REF(MAX(VR17,VR18),1)) AND REF(B9,2)>=S9,L*0.97,13);\n\
+DRAWICON(REF(S1,1) AND (REF(VR17=B9,H*1.03,14);\n\
+\n\
+DRAWKLINE_IF(VR17>VR18,HIGH,CLOSE,LOW,OPEN),COLORRED;\n\
+DRAWKLINE_IF(VR17X_3 AND X_2>X_4,X_2+X_3/2+X_5/4,IF(X_3>X_4 AND X_3>X_2,X_3+X_2/2+X_5/4,X_4+X_5/4));\n\
+X_7:=CLOSE-X_1+(CLOSE-OPEN)/2+X_1-REF(OPEN,1);\n\
+X_8:=8*X_7/X_6*MAX(X_2,X_3);\n\
+ASI:SUM(X_8,0),LINETHICK2;\n\
+MASI:MA(ASI,N1),LINETHICK2;"
+ };
+
+ return data;
+}
+
+/*
+History
+The Donchian Channels (DC) indicator was created by the famous commodities trader Richard Donchian. Donchian would become known as The Father of Trend Following.
+
+Calculation
+For this example, a 20 day period is used which is a very commonly used timeframe.
+
+Upper Channel = 20 Day High
+Lower Channel = 20 Day Low
+Middle Channel = (20 Day High + 20 Day Low)/2
+*/
+JSIndexScript.prototype.DC = function ()
+{
+ let data =
+ {
+ Name: 'DC', Description: '唐奇安通道', IsMainIndex: true,
+ Args: [{ Name: 'N1', Value: 20 }],
+ Script: //脚本
+"UPPER:HHV(H,N1),COLORBLUE,LINETHICK2;\n\
+LOWER:LLV(L,N1),COLORBLUE,LINETHICK2;\n\
+MIDDLE:(UPPER+LOWER)/2,COLORRED,LINETHICK3;"
+ };
+
+ return data;
+}
+
+/*
+双重指数移动均线(DEMA)由Patrick Mulloy开发并于1994年2月在"股票与商品期货的技术分析"杂志中出版。
+用于平滑价格系列并被直接应用到金融证券的价格图表中。此外,它还用于平滑其他指标的价值。
+
+DEMA的优势是在锯齿状的价格移动中清除错误信号并允许趋势强劲时保持仓位。
+
+计算
+该指标基于指数移动平均线 (EMA). 从EMA值中查看价格偏差错误:
+err(i) = Price(i) - EMA(Price, N, i)
+
+此处:
+err(i) ― 当前EMA误差;
+Price(i) ― 当前价格;
+EMA(Price, N, i) ― 价格系列的以N为周期的EMA的当前值。
+
+添加指数平均线错误值到价格指数移动平均数值,可以获得EDMA;
+DEMA(i) = EMA(Price,N,i)+ EMA(err,N,i) = EMA(Price,N,i)+EMA(Price-EMA(Price,N,i),N,i) =
+= 2*EMA(Price,N,i)-EMA(Price-EMA(Price,N,i),N,i)=2*EMA(Price,N,i)-EMA2(Price,N,i)
+
+此处:
+EMA(err, N, i) ― 误差err的指数均线的当前值;
+EMA2(Price, N, i) ― 价格的二重连续平滑的当前值。
+*/
+JSIndexScript.prototype.DEMA = function ()
+{
+ let data =
+ {
+ Name: 'DEMA', Description: '双重指数移动均线', IsMainIndex: true,
+ Args: [{ Name: 'N1', Value: 10 }],
+ Script: //脚本
+"ERR:=C-EMA(C,N1);\n\
+DEMA:EMA(C,10)+EMA(ERR,N1);"
+ };
+
+ return data;
+}
+
+/*
+Calculation
+There are five steps in calculating VWAP:
+
+Calculate the Typical Price for the period.
+ [(High + Low + Close)/3)]
+Multiply the Typical Price by the period Volume.
+ (Typical Price x Volume)
+Create a Cumulative Total of Typical Price.
+ Cumulative(Typical Price x Volume)
+Create a Cumulative Total of Volume.
+ Cumulative(Volume)
+Divide the Cumulative Totals.
+ VWAP = Cumulative(Typical Price x Volume) / Cumulative(Volume)
+*/
+
+JSIndexScript.prototype.VWAP = function ()
+{
+ let data =
+ {
+ Name: 'VWAP', Description: '成交量加权平均价', IsMainIndex: true,
+ Args: [{ Name: 'N1', Value: 10 }],
+ Script: //脚本
+"PRICE:=(H+L+C)/3;\n\
+T2:=VOL*PRICE;\n\
+VWAP:SUM(T2,0)/SUM(VOL,0);"
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.SQJZ = function ()
+{
+ let data =
+ {
+ Name: 'SQJZ', Description: '神奇九转', IsMainIndex: true,
+ Script: //脚本
+"B:=C][=9 AND REFXV(COUNT(B,9),8)=9);\n\
+DRAWNUMBER(B1 AND REF(B,1)=0,L,1),COLORMAGENTA;\n\
+B2:=(N=5 AND REFXV(COUNT(B,6),4)=6) OR (N=6 AND REFXV(COUNT(B,7),5)=7) OR (N=7 AND REFXV(COUNT(B,8),6)=8) OR (N>=8 AND REFXV(COUNT(B,9),7)=9);\n\
+DRAWNUMBER(B2 AND REF(B,2)=0,L,2),COLORMAGENTA;\n\
+B8:=(N=1 AND COUNT(B,8)=8) OR (N>=2 AND REFXV(COUNT(B,9),1)=9);\n\
+DRAWNUMBER(B8 AND REF(B,8)=0,L,8),COLORMAGENTA;\n\
+B9:=(N>=1 AND COUNT(B,9)=9);\n\
+DRAWNUMBER(B9 AND REF(B,9)=0,L,9),COLORBROWN;\n\
+S:=C>REF(C,4);\n\
+S1:=(N=6 AND REFXV(COUNT(S,6),5)=6) OR (N=7 AND REFXV(COUNT(S,7),6)=7) OR (N=8 AND REFXV(COUNT(S,8),7)=8) OR (N>=9 AND REFXV(COUNT(S,9),8)=9);\n\
+DRAWNUMBER(S1 AND REF(S,1)=0,H,1),COLORMAGENTA,DRAWABOVE;\n\
+S2:=(N=5 AND REFXV(COUNT(S,6),4)=6) OR (N=6 AND REFXV(COUNT(S,7),5)=7) OR (N=7 AND REFXV(COUNT(S,8),6)=8) OR (N>=8 AND REFXV(COUNT(S,9),7)=9);\n\
+DRAWNUMBER(S2 AND REF(S,2)=0,H,2),COLORMAGENTA,DRAWABOVE;\n\
+S8:=(N=1 AND COUNT(S,8)=8) OR (N>=2 AND REFXV(COUNT(S,9),1)=9);\n\
+DRAWNUMBER(S8 AND REF(S,8)=0,H,8),COLORMAGENTA,DRAWABOVE;\n\
+S9:=(N>=1 AND COUNT(S,9)=9);\n\
+DRAWNUMBER(S9 AND REF(S,9)=0,H,9),COLORGREEN,DRAWABOVE;"
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.XT = function ()
+{
+ let data =
+ {
+ Name: 'XT', Description: '箱体', IsMainIndex: true,
+ Args: [{ Name: 'N', Value: 10 }],
+ Script: //脚本
+"【箱顶】:PEAK(CLOSE,N,1)*0.98;\n\
+【箱底】:TROUGH(CLOSE,N,1)*1.02;\n\
+【箱高】:100*(【箱顶】-【箱底】)/【箱底】,NODRAW;"
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.CFJT = function ()
+{
+ let data =
+ {
+ Name: 'CFJT', Description: '财富阶梯', IsMainIndex: true,
+ Script: //脚本
+"突破:=REF(EMA(C,14),1);\n\
+A1X:=(EMA(C,10)-突破)/突破*100;\n\
+多方:=IF(A1X>=0,REF(EMA(C,10),BARSLAST(CROSS(A1X,0))+1),DRAWNULL);\n\
+空方:=IF(A1X<0,REF(EMA(C,10),BARSLAST(CROSS(0,A1X))+1),DRAWNULL);\n\
+STICKLINE(A1X>=0,多方,突破,110,0),COLORRED;\n\
+STICKLINE(A1X<0,空方,突破,110,0),COLORGREEN;"
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.CYX = function ()
+{
+ let data =
+ {
+ Name: 'CYX', Description: '撑压线', IsMainIndex: true,
+ Args: [{ Name: 'N', Value: 7 }],
+ Script: //脚本
+"Z1:=STRCAT(HYBLOCK,' ');\n\
+Z2:=STRCAT(Z1,DYBLOCK);\n\
+Z3:=STRCAT(Z2,' ');\n\
+DRAWTEXT_FIX(ISLASTBAR,0,0,0,STRCAT(Z3,GNBLOCK)),COLOR00C0C0;\n\
+A1:=REF(H,N)=HHV(H,2*N+1);\n\
+B1:=FILTER(A1,N);\n\
+C1:=BACKSET(B1,N+1);\n\
+D1:=FILTER(C1,N);\n\
+A2:=REF(L,N)=LLV(L,2*N+1);\n\
+B2:=FILTER(A2,N);\n\
+C2:=BACKSET(B2,N+1);\n\
+D2:=FILTER(C2,N);\n\
+E1:=(REF(LLV(L,2*N),1)+REF(HHV(H,2*N),1))/2;\n\
+E2:=(H+L)/2;\n\
+H1:=(D1 AND NOT(D2 AND E1>=E2)) OR ISLASTBAR OR BARSCOUNT(C)=1;\n\
+L1:=(D2 AND NOT(D1 AND E1=E2);\n\
+X1:=REF(BARSLAST(H1),1)+1;\n\
+F1:=BACKSET(H1 AND COUNT(L1,X1)>0,LLVBARS(IF(L1,L,10000),X1));\n\
+G1:=F1>REF(F1,1);\n\
+I1:=BACKSET(G1,2);\n\
+LD:=I1>REF(I1,1);\n\
+L2:=LD OR ISLASTBAR OR BARSCOUNT(C)=1;\n\
+X2:=REF(BARSLAST(L2),1)+1;\n\
+F2:=BACKSET(L2 AND COUNT(H2,X2)>0,HHVBARS(IF(H2,H,0),X2));\n\
+G2:=F2>REF(F2,1);\n\
+I2:=BACKSET(G2,2);\n\
+HD:=I2>REF(I2,1);\n\
+R1:=BACKSET(ISLASTBAR,BARSLAST(HD)+1);\n\
+S1:=R1>REF(R1,1);\n\
+T1:=BACKSET(ISLASTBAR,BARSLAST(LD)+1);\n\
+U1:=T1>REF(T1,1);\n\
+R2:=BACKSET(S1,REF(BARSLAST(HD),1)+2);\n\
+S2:=R2>REF(R2,1);\n\
+T2:=BACKSET(U1,REF(BARSLAST(LD),1)+2);\n\
+U2:=T2>REF(T2,1);\n\
+DRAWLINE(S2,H,S1,H,1),LINETHICK2,COLORRED;\n\
+DRAWLINE(U2,L,U1,L,1),LINETHICK2,COLORGREEN;"
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.WAVE = function ()
+{
+ let data =
+ {
+ Name: 'WAVE', Description: '波浪分析', IsMainIndex: true,
+ Args: [{ Name: 'N', Value: 5 }],
+ Script: //脚本
+"ZIG(3,N);"
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.ShareholderCount=function()
+{
+ let data =
+ {
+ Name: '散户线', Description: '散户线', IsMainIndex: false,
+ Script: //脚本
+"GPJYVALUE(1,1,1);"
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.NXTS=function()
+{
+ let data =
+ {
+ Name: 'NXTS', Description: '牛熊天数', IsMainIndex: false,
+ Args: [{ Name: 'N', Value: 20 }],
+ Script: //脚本
+"Z:=ZIG(C,N);\n\
+高点:=Z>REF(Z,1) AND Z>REFX(Z,1);\n\
+低点:=Z][ND OR COUNT(高点,0)=0) AND ND>0 AND (HHV(C,ND)-REF(C,ND))/REF(C,ND)>(N/100);\n\
+N2:=NG0 AND (LLV(C,NG)-REF(C,NG))/REF(C,NG)>=-(N/100);\n\
+N3:=NG(N/100);\n\
+N5:=COUNT(低点,0)=0 AND NG>0 AND (LLV(C,NG)-REF(C,NG))/REF(C,NG)>=-(N/100);\n\
+N6:=COUNT(低点,0)=0 AND NG=0;\n\
+X1:=(NG0 AND (LLV(C,NG)-REF(C,NG))/REF(C,NG)<-(N/100);\n\
+X2:=NG>ND AND ND>0 AND (HHV(C,ND)-REF(C,ND))/REF(C,ND)<=(N/100);\n\
+X3:=NG>ND AND ND=0;\n\
+X4:=COUNT(高点 OR 低点,0)=0 AND (LLV(C,0)-REF(C,BARSSINCE(C)))/REF(C,BARSSINCE(C))<-(N/100);\n\
+X5:=COUNT(高点,0)=0 AND ND>0 AND (HHV(C,ND)-REF(C,ND))/REF(C,ND)<=(N/100);\n\
+X6:=COUNT(高点,0)=0 AND ND=0;\n\
+牛市天数:IF(N4 OR N5 OR N6,D0,IF(N1 OR N2 OR N3,DD,0)),COLORRED;\n\
+熊市天数:IF(X4 OR X5 OR X6,D0,IF(X1 OR X2 OR X3,DG,0)),COLORGREEN;"
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.FKX=function()
+{
+ let data =
+ {
+ Name: 'FKX', Description: '反K线', IsMainIndex: false,
+ Script: //脚本
+"DRAWKLINE(-LOW, -OPEN, -HIGH, -CLOSE);"
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.Margin4=function()
+{
+ let data =
+ {
+ Name: '两融资金', Description: '两融资金', IsMainIndex: false,
+ Script: //脚本
+"TMPV:=IF(FINANCE(3)==0,REF(SCJYVALUE(1,1,1),1),REF(GPJYVALUE(3,1,1),1));\n\
+TMPV1:=IF(FINANCE(3)==0,SCJYVALUE(1,1,0),GPJYVALUE(3,1,0));\n\
+两融:IF(TMPV==0 OR TMPV1==0,DRAWNULL,IF(FINANCE(3)==0,(SCJYVALUE(1,1,1)-REF(SCJYVALUE(1,1,1),1))/10000-(SCJYVALUE(1,2,1)-REF(SCJYVALUE(1,2,1),1))/10000,((GPJYVALUE(3,1,1)-REF(GPJYVALUE(3,1,1),1))-((GPJYVALUE(3,2,1)*C/10000-(REF(GPJYVALUE(3,2,1),1)*REF(C,1)/10000)))))),NODRAW;\n\
+STICKLINE(两融>0,0,两融,2,0),COLORRED;\n\
+STICKLINE(两融<0,0,两融,2,0),COLORCYAN;"
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.ZSDB=function()
+{
+ let data =
+ {
+ Name: 'ZSDB', Description: '指数对比(副图,需下载日线)', IsMainIndex: false,
+ Script: //脚本
+"A:=REF(INDEXC,1);\n\
+指数涨幅:IF(A>0,(INDEXC-A)*100/A,0),NODRAW;\n\
+DRAWKLINE(INDEXH,INDEXO,INDEXL,INDEXC);"
+ };
+
+ return data;
+}
+
+JSIndexScript.prototype.NineTurns=function()
+{
+ let data =
+ {
+ Name: '神奇九转', Description: '九转指标', IsMainIndex: true,
+ Script: //脚本
+"A1:=C>REF(C,4);\n\
+A2:=C][REF(C,4);\n\
+D1:=B2 AND REF(B1,1);\n\
+D2:=B2 AND REF(D1,1);\n\
+D3:=B2 AND REF(D2,1);\n\
+D4:=B2 AND REF(D3,1);\n\
+D5:=B2 AND REF(D4,1);\n\
+D6:=B2 AND REF(D5,1);\n\
+D7:=B2 AND REF(D6,1);\n\
+D8:=B2 AND REF(D7,1);\n\
+D9:=B2 AND REF(D8,1);\n\
+D10:=B2 AND REF(D9,1);\n\
+D11:=B2 AND REF(D10,1);\n\
+D12:=B2 AND REF(D11,1);\n\
+D13:=B2 AND REF(D12,1);\n\
+D14:=B2 AND REF(D13,1);\n\
+DRAWTEXT(D1,H*1.010,'1'),COLORBLUE;\n\
+DRAWTEXT(D2,H*1.010,'2'),COLORBLUE;\n\
+DRAWTEXT(D3,H*1.010,'3'),COLORBLUE;\n\
+DRAWTEXT(D4,H*1.010,'4'),COLORBLUE;\n\
+DRAWTEXT(D5,H*1.010,'5'),COLORBLUE;\n\
+DRAWTEXT(D6,H*1.010,'6'),COLORBLUE;\n\
+DRAWTEXT(D7,H*1.010,'7'),COLORBLUE;\n\
+DRAWTEXT(D8,H*1.010,'8'),COLORBLUE;\n\
+DRAWTEXT(D9,H*1.010,'9'),COLORGREEN;"
+ };
+
+ return data;
+}
+
+
+
+JSIndexScript.prototype.TEST = function ()
+{
+ let data =
+ {
+ Name: 'TEST', Description: '测试脚本', IsMainIndex: false,
+ Args: [{ Name: 'N', Value: 10 }],
+ Script: //脚本
+ "DRAWCHANNEL(OPEN>C,H,L, 'RGB(255,94,102)', 2 ,'5,5','RGBA(58,20,62,0.3)' );"
+ };
+
+ return data;
+}
+
+
+
+/*
+ Copyright (c) 2018 jones
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ 开源项目 https://github.com/jones2000/HQChart
+
+ jones_2000@163.com
+
+ 封装行情类图形控件 (H5版本)
+*/
+
+
+//日志输出类
+if (!JSConsole)
+{
+ var JSConsole=
+ {
+ Chart:{ Log:console.log, Warn:console.warn }, //图形日志
+ Complier:{ Log:console.log, Warn:console.warn } //编译器日志
+ };
+}
+
+
+function JSChart(divElement, bOffscreen)
+{
+ this.DivElement=divElement;
+ this.DivToolElement=null; //工具条
+ this.JSChartContainer; //画图控件
+
+ //h5 canvas
+ this.CanvasElement=document.createElement("canvas");
+ this.CanvasElement.className='jschart-drawing';
+ this.CanvasElement.id=Guid();
+ this.CanvasElement.setAttribute("tabindex",0);
+ if (this.CanvasElement.style) this.CanvasElement.style.outline='none';
+ if(divElement.hasChildNodes())
+ {
+ JSConsole.Chart.Log("[JSChart::JSChart] divElement hasChildNodes", divElement.childNodes);
+ }
+ divElement.appendChild(this.CanvasElement);
+
+ //离屏
+ this.OffscreenCanvasElement;
+ if (bOffscreen==true) this.OffscreenCanvasElement=document.createElement("canvas");
+
+ //改参数div
+ this.ModifyIndexDialog=new ModifyIndexDialog(divElement);
+ this.ChangeIndexDialog=new ChangeIndexDialog(divElement);
+ this.MinuteDialog=new MinuteDialog(divElement);
+
+ this.OnSize=function(option) //{ Type:1 新版本OnSize Redraw:是否重绘 }
+ {
+ //画布大小通过div获取
+ var height=parseInt(this.DivElement.style.height.replace("px",""));
+ if (this.ToolElement)
+ {
+ //TODO调整工具条大小
+ height-=this.ToolElement.style.height.replace("px",""); //减去工具条的高度
+ }
+
+ this.CanvasElement.height=height;
+ this.CanvasElement.width=parseInt(this.DivElement.style.width.replace("px",""));
+ this.CanvasElement.style.width=this.CanvasElement.width+'px';
+ this.CanvasElement.style.height=this.CanvasElement.height+'px';
+
+ var pixelTatio = GetDevicePixelRatio(); //获取设备的分辨率
+ this.CanvasElement.height*=pixelTatio;
+ this.CanvasElement.width*=pixelTatio;
+
+ if (this.OffscreenCanvasElement)
+ {
+ this.OffscreenCanvasElement.height=this.CanvasElement.height;
+ this.OffscreenCanvasElement.width=this.CanvasElement.width;
+ }
+
+ JSConsole.Chart.Log(`[JSChart::OnSize] devicePixelRatio=${window.devicePixelRatio}, height=${this.CanvasElement.height}, width=${this.CanvasElement.width}`);
+
+ if (option && option.Redraw==false) return;
+
+ if (this.JSChartContainer)
+ {
+ if (this.JSChartContainer.OnSize && option && option.Type==1)
+ {
+ this.JSChartContainer.OnSize();
+ }
+ else
+ {
+ if (this.JSChartContainer.Frame) this.JSChartContainer.Frame.SetSizeChage(true);
+ this.JSChartContainer.Draw();
+ }
+ }
+ }
+
+ //手机屏需要调整 间距
+ this.AdjustChartBorder=function(chart)
+ {
+ var pixelTatio = GetDevicePixelRatio(); //获取设备的分辨率
+
+ chart.Frame.ChartBorder.Left*=pixelTatio;
+ chart.Frame.ChartBorder.Right*=pixelTatio;
+ chart.Frame.ChartBorder.Top*=pixelTatio;
+ chart.Frame.ChartBorder.Bottom*=pixelTatio;
+ }
+
+ this.AdjustTitleHeight=function(chart)
+ {
+ var pixelTatio = GetDevicePixelRatio(); //获取设备的分辨率
+
+ for(var i=0;i=0) chart.DragMode=option.KLine.DragMode;
+ if (option.KLine.Right>=0) chart.Right=option.KLine.Right;
+ if (option.KLine.Period>=0) chart.Period=option.KLine.Period;
+ if (option.KLine.MaxReqeustDataCount>0) chart.MaxReqeustDataCount=option.KLine.MaxReqeustDataCount;
+ if (option.KLine.Info && option.KLine.Info.length>0) chart.SetKLineInfo(option.KLine.Info,false);
+ if (option.KLine.IndexTreeApiUrl) chart.ChangeIndexDialog.IndexTreeApiUrl=option.KLine.IndexTreeApiUrl;
+ if (option.KLine.KLineDoubleClick==false) chart.MinuteDialog=this.MinuteDialog=null;
+ if (option.KLine.IndexTreeApiUrl!=null) chart.ChangeIndexDialog.IndexTreeApiUrl=option.KLine.IndexTreeApiUrl;
+ if (option.KLine.IsShowTooltip==false) chart.IsShowTooltip=false;
+ if (option.KLine.MaxRequestMinuteDayCount>0) chart.MaxRequestMinuteDayCount=option.KLine.MaxRequestMinuteDayCount;
+ if (option.KLine.DrawType) chart.KLineDrawType=option.KLine.DrawType;
+ if (option.KLine.FirstShowDate>19910101) chart.CustomShow={ Date:option.KLine.FirstShowDate, PageSize:option.KLine.PageSize };
+ if (option.KLine.RightSpaceCount>0) chart.RightSpaceCount=option.KLine.RightSpaceCount;
+ if (option.KLine.ZoomType>0) chart.ZoomType=option.KLine.ZoomType;
+ if (option.KLine.DataWidth>=1) chart.KLineSize={ DataWidth:option.KLine.DataWidth };
+ if (IFrameSplitOperator.IsNumber(option.KLine.RightFormula)) chart=RightFormula=option.KLine.RightFormula;
+ }
+
+ if (option.EnableFlowCapital)
+ {
+ var item=option.EnableFlowCapital;
+ if (item.BIT==true) chart.EnableFlowCapital.BIT=item.BIT;
+ }
+
+ if (IFrameSplitOperator.IsBool(option.EnableBorderDrag))
+ {
+ chart.EnableBorderDrag=option.EnableBorderDrag;
+ }
+
+ if (option.Page)
+ {
+ if (option.Page.Day && option.Page.Day.Enable==true) chart.Page.Day.Enable=true;
+ if (option.Page.Minute && option.Page.Minute.Enable==true) chart.Page.Minute.Enable=true;
+ }
+
+ if (option.DragDownload)
+ {
+ if (option.DragDownload.Day && option.DragDownload.Day.Enable==true) chart.DragDownload.Day.Enable=true;
+ if (option.DragDownload.Minute && option.DragDownload.Minute.Enable==true) chart.DragDownload.Minute.Enable=true;
+ }
+
+ if (option.Language)
+ {
+ if (option.Language==='CN') chart.LanguageID=JSCHART_LANGUAGE_ID.LANGUAGE_CHINESE_ID;
+ else if(option.Language==='EN') chart.LanguageID=JSCHART_LANGUAGE_ID.LANGUAGE_ENGLISH_ID;
+ }
+
+ if (option.SourceDatatLimit) chart.SetSourceDatatLimit(option.SourceDatatLimit);
+
+ if (option.DrawPicture) //画图工具
+ {
+ if (option.DrawPicture.StorageKey && chart.ChartDrawStorage) chart.ChartDrawStorage.Load(option.DrawPicture.StorageKey);
+ }
+
+ if (option.DrawTool) //画图工具
+ {
+ if (option.DrawTool.StorageKey && chart.ChartDrawStorage) chart.ChartDrawStorage.Load(option.DrawTool.StorageKey);
+ }
+
+ if (IFrameSplitOperator.IsNumber(option.StepPixel)) chart.StepPixel=option.StepPixel;
+ if (option.ZoomStepPixel>0) chart.ZoomStepPixel=option.ZoomStepPixel;
+ if (option.IsApiPeriod==true) chart.IsApiPeriod=option.IsApiPeriod;
+
+ if (!option.Windows || option.Windows.length<=0) return null;
+
+ //创建子窗口
+ chart.Create(option.Windows.length, option.Listener);
+
+ if (option.Border)
+ {
+ var item=option.Border;
+ if (IFrameSplitOperator.IsNumber(option.Border.Left)) chart.Frame.ChartBorder.Left=option.Border.Left;
+ else option.Border.Left=chart.Frame.ChartBorder.Left;
+ if (IFrameSplitOperator.IsNumber(option.Border.Right)) chart.Frame.ChartBorder.Right=option.Border.Right;
+ else option.Border.Right=chart.Frame.ChartBorder.Right;
+ if (IFrameSplitOperator.IsNumber(option.Border.Top)) chart.Frame.ChartBorder.Top=option.Border.Top;
+ else option.Border.Top=chart.Frame.ChartBorder.Top;
+ if (IFrameSplitOperator.IsNumber(option.Border.Bottom)) chart.Frame.ChartBorder.Bottom=option.Border.Bottom;
+ else option.Border.Bottom=chart.Frame.ChartBorder.Bottom;
+
+ if (item.AutoLeft) chart.Frame.AutoLeftBorder=item.AutoLeft;
+ if (item.AutoRight) chart.Frame.AutoRightBorder=item.AutoRight;
+ }
+
+ this.AdjustChartBorder(chart);
+
+ if (option.KLine)
+ {
+ if (option.KLine.PageSize > 0) //一屏显示的数据个数
+ {
+ let pageSize = chart.GetMaxMinPageSize();
+ if (pageSize.Max>10 && pageSize.Max < option.KLine.PageSize) chart.PageSize = pageSize.Max;
+ else if (pageSize.Min>10 && pageSize.Min> option.KLine.PageSize) chart.PageSize=pageSize.Min;
+ else chart.PageSize = option.KLine.PageSize;
+ }
+ }
+
+ //取消显示十字光标刻度信息
+ if (option.IsCorssOnlyDrawKLine===true) chart.ChartCorssCursor.IsOnlyDrawKLine=option.IsCorssOnlyDrawKLine;
+ if (option.CorssCursorTouchEnd===true) chart.CorssCursorTouchEnd = option.CorssCursorTouchEnd;
+ if (option.IsClickShowCorssCursor==true) chart.IsClickShowCorssCursor=option.IsClickShowCorssCursor;
+ if (option.CorssCursorInfo)
+ {
+ var item=option.CorssCursorInfo;
+ if (!isNaN(option.CorssCursorInfo.Left)) chart.ChartCorssCursor.ShowTextMode.Left=option.CorssCursorInfo.Left;
+ if (!isNaN(option.CorssCursorInfo.Right)) chart.ChartCorssCursor.ShowTextMode.Right=option.CorssCursorInfo.Right;
+ if (!isNaN(option.CorssCursorInfo.Bottom)) chart.ChartCorssCursor.ShowTextMode.Bottom=option.CorssCursorInfo.Bottom;
+ if (option.CorssCursorInfo.IsShowCorss===false) chart.ChartCorssCursor.IsShowCorss=option.CorssCursorInfo.IsShowCorss;
+ if (option.CorssCursorInfo.IsShowClose == true) chart.ChartCorssCursor.IsShowClose = option.CorssCursorInfo.IsShowClose; //Y轴显示收盘价
+ if (option.CorssCursorInfo.PressTime) chart.PressTime=option.CorssCursorInfo.PressTime; //长按显示十字光标的时间
+ if (IFrameSplitOperator.IsNumber(option.CorssCursorInfo.HPenType)) chart.ChartCorssCursor.HPenType=option.CorssCursorInfo.HPenType;
+ if (option.CorssCursorInfo.VPenType>0) chart.ChartCorssCursor.VPenType=option.CorssCursorInfo.VPenType;
+ if (IFrameSplitOperator.IsNumber(item.VLineType)) chart.ChartCorssCursor.VLineType=item.VLineType;
+ if (option.CorssCursorInfo.DateFormatType>0) chart.ChartCorssCursor.StringFormatX.DateFormatType=option.CorssCursorInfo.DateFormatType;
+ if (IFrameSplitOperator.IsBool(item.IsDrawXRangeBG)) chart.ChartCorssCursor.IsDrawXRangeBG=item.IsDrawXRangeBG;
+ if (IFrameSplitOperator.IsBool(option.CorssCursorInfo.IsFixXLastTime)) chart.ChartCorssCursor.IsFixXLastTime=option.CorssCursorInfo.IsFixXLastTime;
+ }
+
+ //保存十字光标文字高度
+ option.CorssCursor={};
+ option.CorssCursor.TitleHeight=chart.ChartCorssCursor.TextHeight;
+
+
+
+ if (option.Frame)
+ {
+ for(var i=0;i=0) chart.Frame.SubFrame[i].Frame.ChartBorder.TopSpace=item.TopSpace;
+ if (item.BottomSpace>=0) chart.Frame.SubFrame[i].Frame.ChartBorder.BottomSpace=item.BottomSpace;
+
+ if (item.RightTextPosition>0) chart.Frame.SubFrame[i].Frame.YTextPosition[1]=item.RightTextPosition;
+ if (item.LeftTextPosition>0) chart.Frame.SubFrame[i].Frame.YTextPosition[0]=item.LeftTextPosition;
+
+ if (item.IsShowXLine==false) chart.Frame.SubFrame[i].Frame.IsShowXLine=item.IsShowXLine;
+ if (item.IsShowYLine==false) chart.Frame.SubFrame[i].Frame.IsShowYLine=item.IsShowYLine;
+ if (IFrameSplitOperator.IsNumber(item.YTextBaseline)) chart.Frame.SubFrame[i].Frame.YTextBaseline=item.YTextBaseline;
+
+ if (item.YCoordinateType>0) chart.Frame.SubFrame[0].Frame.YSplitOperator.CoordinateType=item.YCoordinateType;
+ if (item.IsYReverse==true) chart.Frame.SubFrame[0].Frame.CoordinateType=1; //反转坐标
+ if (IFrameSplitOperator.IsNumber(item.PercentageTextFormat)) subFrame.YSplitOperator.PercentageTextFormat=item.PercentageTextFormat; //百分比坐标格式
+
+ if (item.DefaultYMaxMin) chart.Frame.SubFrame[i].Frame.YSplitOperator.DefaultYMaxMin=item.DefaultYMaxMin;
+ if (IFrameSplitOperator.IsBool(item.EnableRemoveZero)) chart.Frame.SubFrame[i].Frame.YSplitOperator.EnableRemoveZero=item.EnableRemoveZero;
+ if (IFrameSplitOperator.IsPlusNumber(item.MinYDistance)) chart.Frame.SubFrame[i].Frame.MinYDistance=item.MinYDistance;
+ if (IFrameSplitOperator.IsNumber(item.BorderLine)) chart.Frame.SubFrame[i].Frame.BorderLine=item.BorderLine;
+ if (IFrameSplitOperator.IsBool(item.IsShowIndexTitle)) chart.Frame.SubFrame[i].Frame.IsShowIndexTitle=item.IsShowIndexTitle;
+ if (IFrameSplitOperator.IsBool(item.IsDrawTitleBottomLine)) subFrame.IsDrawTitleBottomLine=item.IsDrawTitleBottomLine;
+ }
+ }
+
+ if (option.KLine)
+ {
+ if (option.KLine.ShowKLine == false) chart.ChartPaint[0].IsShow = false;
+ if (option.KLine.InfoPosition>0) chart.ChartPaint[0].InfoPosition=option.KLine.InfoPosition;
+ if (option.KLine.IsShowMaxMinPrice == false) chart.ChartPaint[0].IsShowMaxMinPrice=option.KLine.IsShowMaxMinPrice;
+ }
+
+ if(option.KLineTitle)
+ {
+ if(option.KLineTitle.IsShowName==false) chart.TitlePaint[0].IsShowName=false;
+ if(option.KLineTitle.IsShowSettingInfo==false) chart.TitlePaint[0].IsShowSettingInfo=false;
+ if(option.KLineTitle.IsShow == false) chart.TitlePaint[0].IsShow = false;
+ }
+
+ //叠加股票
+
+ if (option.Overlay)
+ {
+ for(var i=0;i0) chart.WindowIndex[i].StringFormat=item.StringFormat;
+ if (item.FloatPrecision>=0) chart.WindowIndex[i].FloatPrecision=item.FloatPrecision;
+ }
+
+ }
+
+ if (item.Modify!=null) chart.Frame.SubFrame[i].Frame.ModifyIndex=item.Modify;
+ if (item.Change!=null) chart.Frame.SubFrame[i].Frame.ChangeIndex=item.Change;
+ if (item.Close!=null) chart.Frame.SubFrame[i].Frame.CloseIndex=item.Close;
+ if (item.Overlay!=null) chart.Frame.SubFrame[i].Frame.OverlayIndex=item.Overlay;
+ if (item.IsDrawTitleBG==true) chart.Frame.SubFrame[i].Frame.IsDrawTitleBG=item.IsDrawTitleBG;
+
+ if (IFrameSplitOperator.IsNumber(item.TitleHeight)) chart.Frame.SubFrame[i].Frame.ChartBorder.TitleHeight=item.TitleHeight;
+ else item.TitleHeight=chart.Frame.SubFrame[i].Frame.ChartBorder.TitleHeight;
+ if (item.IsShowTitleArraw==false) chart.Frame.SubFrame[i].Frame.IsShowTitleArraw=false;
+ if (item.IsShowIndexName==false) chart.Frame.SubFrame[i].Frame.IsShowIndexName=false;
+ if (item.IsShowOverlayIndexName==false) chart.Frame.SubFrame[i].Frame.IsShowOverlayIndexName=false;
+ if (item.IndexParamSpace>=0) chart.Frame.SubFrame[i].Frame.IndexParamSpace=item.IndexParamSpace;
+ if (item.OverlayIndexType)
+ {
+ if (IFrameSplitOperator.IsNumber(item.OverlayIndexType.Position)) chart.Frame.SubFrame[i].Frame.OverlayIndexType.Position=item.OverlayIndexType.Position;
+ if (IFrameSplitOperator.IsNumber(item.OverlayIndexType.LineSpace)) chart.Frame.SubFrame[i].Frame.OverlayIndexType.LineSpace=item.OverlayIndexType.LineSpace;
+ }
+ }
+
+ //叠加指标宽度
+ if (option.OverlayIndexFrameWidth>40) chart.OverlayIndexFrameWidth=option.OverlayIndexFrameWidth;
+
+ //叠加指标
+ if (IFrameSplitOperator.IsNonEmptyArray(option.OverlayIndex))
+ {
+ for(var i=0;i=chart.Frame.SubFrame.length) continue;
+
+ var itemString = JSON.stringify(item);
+ var obj = JSON.parse(itemString);
+ if (item.Index) obj.IndexName=item.Index;
+ if (item.Windows>=0) obj.WindowIndex=item.Windows;
+ chart.CreateOverlayWindowsIndex(obj);
+ }
+
+ }
+
+ this.AdjustTitleHeight(chart);
+
+ return chart;
+ }
+
+ //自定义指数历史K线图
+ this.CreateCustomKLineChartContainer=function(option)
+ {
+ var chart=new CustomKLineChartContainer(this.CanvasElement);
+
+ //创建改参数div
+ chart.ModifyIndexDialog=this.ModifyIndexDialog;
+ chart.ChangeIndexDialog=this.ChangeIndexDialog;
+ chart.MinuteDialog=this.MinuteDialog;
+
+ //右键菜单
+ if (option.IsShowRightMenu==true) chart.RightMenu=new KLineRightMenu(this.DivElement);
+
+ if (option.KLine) //k线图的属性设置
+ {
+ if (option.KLine.DragMode>=0) chart.DragMode=option.KLine.DragMode;
+ if (option.KLine.Right>=0) chart.Right=option.KLine.Right;
+ if (option.KLine.Period>=0) chart.Period=option.KLine.Period;
+ if (option.KLine.MaxReqeustDataCount>0) chart.MaxReqeustDataCount=option.KLine.MaxReqeustDataCount;
+ if (option.KLine.Info && option.KLine.Info.length>0) chart.SetKLineInfo(option.KLine.Info,false);
+ if (option.KLine.IndexTreeApiUrl) chart.ChangeIndexDialog.IndexTreeApiUrl=option.KLine.IndexTreeApiUrl;
+ if (option.KLine.KLineDoubleClick==false) chart.MinuteDialog=this.MinuteDialog=null;
+ if (option.KLine.IndexTreeApiUrl!=null) chart.ChangeIndexDialog.IndexTreeApiUrl=option.KLine.IndexTreeApiUrl;
+ if (option.KLine.PageSize>0) chart.PageSize=option.KLine.PageSize;
+ if (option.KLine.IsShowTooltip==false) chart.IsShowTooltip=false;
+ }
+
+ if (option.CustomStock) chart.CustomStock=option.CustomStock;
+ if (option.QueryDate) chart.QueryDate=option.QueryDate;
+
+ if (!option.Windows || option.Windows.length<=0) return null;
+
+ //创建子窗口
+ chart.Create(option.Windows.length);
+
+ if (option.Border)
+ {
+ if (!isNaN(option.Border.Left)) chart.Frame.ChartBorder.Left=option.Border.Left;
+ if (!isNaN(option.Border.Right)) chart.Frame.ChartBorder.Right=option.Border.Right;
+ if (!isNaN(option.Border.Top)) chart.Frame.ChartBorder.Top=option.Border.Top;
+ }
+
+ if (option.IsShowCorssCursorInfo==false) //取消显示十字光标刻度信息
+ {
+ chart.ChartCorssCursor.IsShowText=option.IsShowCorssCursorInfo;
+ }
+
+ if (option.Frame)
+ {
+ for(var i=0;i0) windowsCount+=option.Windows.length; //指标窗口从第3个窗口开始
+ if (option.EnableScrollUpDown==true) chart.EnableScrollUpDown=option.EnableScrollUpDown;
+ if (option.DisableMouse==true) chart.DisableMouse=option.DisableMouse;
+ if (option.ScriptError) chart.ScriptErrorCallback=option.ScriptError; //指标执行错误回调
+ if (IFrameSplitOperator.IsString(option.SplashTitle)) chart.LoadDataSplashTitle=option.SplashTitle;
+ if (IFrameSplitOperator.IsBool(option.EnableSelectRect)) chart.EnableSelectRect=option.EnableSelectRect; //是否启用区间选择
+ if (IFrameSplitOperator.IsBool(option.EnableZoomIndexWindow)) chart.EnableZoomIndexWindow=option.EnableZoomIndexWindow;
+
+ chart.SelectRectDialog=new MinuteSelectRectDialog(this.DivElement);
+
+
+ if (option.Minute) //分钟走势图属性设置
+ {
+ if (option.Minute.IsShowTooltip==false) chart.IsShowTooltip=false;
+ if (option.Minute.DragMode>=0) chart.DragMode=option.Minute.DragMode;
+ }
+
+ if (option.Language)
+ {
+ if (option.Language==='CN') chart.LanguageID=JSCHART_LANGUAGE_ID.LANGUAGE_CHINESE_ID;
+ else if(option.Language==='EN') chart.LanguageID=JSCHART_LANGUAGE_ID.LANGUAGE_ENGLISH_ID;
+ }
+
+ if (option.Info && option.Info.length>0) chart.SetMinuteInfo(option.Info,false);
+
+ if (option.DrawTool) //画图工具
+ {
+ if (option.DrawTool.StorageKey && chart.ChartDrawStorage) chart.ChartDrawStorage.Load(option.DrawTool.StorageKey);
+ }
+
+ if (option.BeforeOpen) //集合竞价
+ {
+ var item=option.BeforeOpen;
+
+ if (IFrameSplitOperator.IsBool(item.IsShow)) chart.IsShowBeforeData=item.IsShow;
+ if (IFrameSplitOperator.IsNumber(item.Width)) chart.ExtendWidth.Left=item.Width;
+ }
+
+ if (option.AfterClose) //收盘集合竞价
+ {
+ var item=option.AfterClose;
+ if (IFrameSplitOperator.IsBool(item.IsShow)) chart.IsShowAfterData=item.IsShow;
+ if (IFrameSplitOperator.IsNumber(item.Width)) chart.ExtendWidth.Right=item.Width;
+ }
+
+ chart.Create(windowsCount,option.Listener); //创建子窗口
+
+ if (option.CorssCursorInfo)
+ {
+ var item=option.CorssCursorInfo;
+ if (!isNaN(option.CorssCursorInfo.Left)) chart.ChartCorssCursor.ShowTextMode.Left=option.CorssCursorInfo.Left;
+ if (!isNaN(option.CorssCursorInfo.Right)) chart.ChartCorssCursor.ShowTextMode.Right=option.CorssCursorInfo.Right;
+ if (!isNaN(option.CorssCursorInfo.Bottom)) chart.ChartCorssCursor.ShowTextMode.Bottom=option.CorssCursorInfo.Bottom;
+ if (option.CorssCursorInfo.IsShowCorss===false) chart.ChartCorssCursor.IsShowCorss=option.CorssCursorInfo.IsShowCorss;
+ if (option.CorssCursorInfo.RightTextFormat>0) chart.ChartCorssCursor.TextFormat.Right=option.CorssCursorInfo.RightTextFormat;
+ if (option.CorssCursorInfo.IsOnlyDrawMinute == true) chart.ChartCorssCursor.IsOnlyDrawMinute = option.CorssCursorInfo.IsOnlyDrawMinute; //Y轴显示收盘价
+ if (IFrameSplitOperator.IsBool(option.CorssCursorInfo.IsFixXLastTime)) chart.ChartCorssCursor.IsFixXLastTime=option.CorssCursorInfo.IsFixXLastTime;
+ }
+
+ if (option.MinuteInfo) chart.CreateMinuteInfo(option.MinuteInfo);
+
+ if (option.IsShowRightMenu==true) chart.RightMenu=new MinuteRightMenu(this.DivElement);
+
+ if (option.DayCount>1) chart.DayCount=option.DayCount;
+
+ if (option.Border)
+ {
+ var item=option.Border;
+ if (!isNaN(option.Border.Left)) chart.Frame.ChartBorder.Left=option.Border.Left;
+ if (!isNaN(option.Border.Right)) chart.Frame.ChartBorder.Right=option.Border.Right;
+ if (!isNaN(option.Border.Top)) chart.Frame.ChartBorder.Top=option.Border.Top;
+ if (!isNaN(option.Border.Bottom)) chart.Frame.ChartBorder.Bottom=option.Border.Bottom;
+
+ if (item.AutoLeft) chart.Frame.AutoLeftBorder=item.AutoLeft;
+ if (item.AutoRight) chart.Frame.AutoRightBorder=item.AutoRight;
+ }
+
+ if (option.SplashTitle) chart.ChartSplashPaint.SplashTitle=option.SplashTitle;
+
+ if (IFrameSplitOperator.IsBool(option.EnableBorderDrag))
+ {
+ chart.EnableBorderDrag=option.EnableBorderDrag;
+ }
+
+ this.AdjustChartBorder(chart);
+
+ if (option.Frame)
+ {
+ for(var i=0;i=0) chart.Frame.SubFrame[i].Height = item.Height;
+ if (item.Custom) chart.Frame.SubFrame[i].Frame.YSplitOperator.Custom=item.Custom;
+ if (item.RightTextFormat>0) chart.Frame.SubFrame[i].Frame.YSplitOperator.RightTextFormat=item.RightTextFormat;
+ if (IFrameSplitOperator.IsNumber(item.TitleHeight)) chart.Frame.SubFrame[i].Frame.ChartBorder.TitleHeight=item.TitleHeight;
+ if (IFrameSplitOperator.IsNumber(item.BorderLine)) chart.Frame.SubFrame[i].Frame.BorderLine=item.BorderLine;
+ if (IFrameSplitOperator.IsBool(item.EnableRemoveZero)) chart.Frame.SubFrame[i].Frame.YSplitOperator.EnableRemoveZero=item.EnableRemoveZero;
+ if (IFrameSplitOperator.IsNumber(item.FloatPrecision)) chart.Frame.SubFrame[i].Frame.YSplitOperator.FloatPrecision=item.FloatPrecision;
+ if (IFrameSplitOperator.IsNumber(item.YTextBaseline)) chart.Frame.SubFrame[i].Frame.YTextBaseline=item.YTextBaseline;
+ }
+
+ chart.UpdateXShowText();
+ }
+
+ if (option.ExtendChart)
+ {
+ for(var i=0;i0) chart.Frame.SubFrame[0].Frame.YSplitOperator.SplitType=option.MinuteLine.SplitType;
+ }
+
+ if(option.MinuteTitle)
+ {
+ var item=option.MinuteTitle;
+ if(IFrameSplitOperator.IsBool(item.IsShowName)) chart.TitlePaint[0].IsShowName=item.IsShowName;
+ if(IFrameSplitOperator.IsBool(item.IsShowDate)) chart.TitlePaint[0].IsShowDate=item.IsShowDate;
+ if(IFrameSplitOperator.IsBool(item.IsShowTime)) chart.TitlePaint[0].IsShowTime=item.IsShowTime;
+ if(IFrameSplitOperator.IsBool(item.IsTitleShowLatestData)) chart.IsTitleShowLatestData=item.IsTitleShowLatestData;
+ //if(option.KLineTitle.IsShow == false) chart.TitlePaint[0].IsShow = false;
+ }
+
+ if (option.CorssCursorTouchEnd===true) chart.CorssCursorTouchEnd = option.CorssCursorTouchEnd;
+ if (option.IsShowBeforeData===true) chart.IsShowBeforeData=option.IsShowBeforeData;
+
+ //分钟数据指标从第3个指标窗口设置
+ if (IFrameSplitOperator.IsNonEmptyArray(option.Windows))
+ {
+ let scriptData = new JSIndexScript();
+ for(var i=0;i0) chart.WindowIndex[index].StringFormat=item.StringFormat;
+ if (item.FloatPrecision>=0) chart.WindowIndex[index].FloatPrecision=item.FloatPrecision;
+ }
+ }
+
+ if (item.Modify!=null) chart.Frame.SubFrame[index].Frame.ModifyIndex=item.Modify;
+ if (item.Change!=null) chart.Frame.SubFrame[index].Frame.ChangeIndex=item.Change;
+ if (item.Close!=null) chart.Frame.SubFrame[index].Frame.CloseIndex=item.Close;
+ if (!isNaN(item.TitleHeight)) chart.Frame.SubFrame[index].Frame.ChartBorder.TitleHeight=item.TitleHeight;
+ }
+ }
+
+ this.AdjustTitleHeight(chart);
+
+ //叠加指标
+ if (IFrameSplitOperator.IsNonEmptyArray(option.OverlayIndex))
+ {
+ for(var i=0;i=chart.Frame.SubFrame.length) continue;
+
+ var itemString = JSON.stringify(item);
+ var obj = JSON.parse(itemString);
+ if (item.Index) obj.IndexName=item.Index;
+ if (item.Windows>=0) obj.WindowIndex=item.Windows;
+ chart.CreateOverlayWindowsIndex(obj);
+ }
+ }
+
+ return chart;
+ }
+
+ //历史分钟走势图
+ this.CreateHistoryMinuteChartContainer=function(option)
+ {
+ var chart=new HistoryMinuteChartContainer(this.CanvasElement);
+
+ var windowsCount=2;
+ if (option.Windows && option.Windows.length>0) windowsCount+=option.Windows.length; //指标窗口从第3个窗口开始
+
+ chart.Create(windowsCount); //创建子窗口
+
+ if (option.IsShowCorssCursorInfo==false) //取消显示十字光标刻度信息
+ {
+ chart.ChartCorssCursor.IsShowText=option.IsShowCorssCursorInfo;
+ }
+
+ if (option.Border)
+ {
+ if (!isNaN(option.Border.Left)) chart.Frame.ChartBorder.Left=option.Border.Left;
+ if (!isNaN(option.Border.Right)) chart.Frame.ChartBorder.Right=option.Border.Right;
+ if (!isNaN(option.Border.Top)) chart.Frame.ChartBorder.Top=option.Border.Top;
+ if (!isNaN(option.Border.Bottom)) chart.Frame.ChartBorder.Bottom=option.Border.Bottom;
+ }
+
+ let scriptData = new JSIndexScript();
+ if (option.Windows)
+ {
+ for(var i=0;i=0) chart.Right=option.KLine.Right;
+ if (option.KLine.Period>=0) chart.Period=option.KLine.Period;
+ if (option.KLine.MaxReqeustDataCount>0) chart.MaxReqeustDataCount=option.KLine.MaxReqeustDataCount;
+ if (option.KLine.Info && option.KLine.Info.length>0) chart.SetKLineInfo(option.KLine.Info,false);
+ if (option.KLine.PageSize>0) chart.PageSize=option.KLine.PageSize;
+ if (option.KLine.IsShowTooltip==false) chart.IsShowTooltip=false;
+ if (option.KLine.MaxRequestMinuteDayCount>0) chart.MaxRequestMinuteDayCount=option.KLine.MaxRequestMinuteDayCount;
+ if (option.KLine.DrawType) chart.KLineDrawType=option.KLine.DrawType;
+ if (option.KLine.RightSpaceCount>0) chart.RightSpaceCount=option.KLine.RightSpaceCount;
+ }
+
+ if (option.Train)
+ {
+ if (option.Train.DataCount) chart.TrainDataCount=option.Train.DataCount;
+ if (option.Train.Callback) chart.TrainCallback=option.Train.Callback;
+ if (option.Train.StartDate) chart.TrainStartDate=option.Train.StartDate;
+ }
+
+ if (!option.Windows || option.Windows.length<=0) return null;
+
+ //创建子窗口
+ chart.Create(option.Windows.length);
+
+ if (option.Border)
+ {
+ if (!isNaN(option.Border.Left)) chart.Frame.ChartBorder.Left=option.Border.Left;
+ if (!isNaN(option.Border.Right)) chart.Frame.ChartBorder.Right=option.Border.Right;
+ if (!isNaN(option.Border.Top)) chart.Frame.ChartBorder.Top=option.Border.Top;
+ if (!isNaN(option.Border.Bottom)) chart.Frame.ChartBorder.Bottom=option.Border.Bottom;
+ }
+
+ this.AdjustChartBorder(chart);
+
+ if (option.IsShowCorssCursorInfo==false) chart.ChartCorssCursor.IsShowText=option.IsShowCorssCursorInfo; //取消显示十字光标刻度信息
+ if (option.IsCorssOnlyDrawKLine===true) chart.ChartCorssCursor.IsOnlyDrawKLine=option.IsCorssOnlyDrawKLine;
+ if (option.CorssCursorTouchEnd===true) chart.CorssCursorTouchEnd = option.CorssCursorTouchEnd;
+ if (option.IsClickShowCorssCursor==true) chart.IsClickShowCorssCursor=option.IsClickShowCorssCursor;
+ if (option.CorssCursorInfo)
+ {
+ if (!isNaN(option.CorssCursorInfo.Left)) chart.ChartCorssCursor.ShowTextMode.Left=option.CorssCursorInfo.Left;
+ if (!isNaN(option.CorssCursorInfo.Right)) chart.ChartCorssCursor.ShowTextMode.Right=option.CorssCursorInfo.Right;
+ if (!isNaN(option.CorssCursorInfo.Bottom)) chart.ChartCorssCursor.ShowTextMode.Bottom=option.CorssCursorInfo.Bottom;
+ if (option.CorssCursorInfo.IsShowCorss===false) chart.ChartCorssCursor.IsShowCorss=option.CorssCursorInfo.IsShowCorss;
+ if (option.CorssCursorInfo.IsShowClose == true) chart.ChartCorssCursor.IsShowClose = option.CorssCursorInfo.IsShowClose; //Y轴显示收盘价
+ if (option.CorssCursorInfo.PressTime) chart.PressTime=option.CorssCursorInfo.PressTime; //长按显示十字光标的时间
+ if (option.CorssCursorInfo.HPenType>0) chart.ChartCorssCursor.HPenType=option.CorssCursorInfo.HPenType;
+ if (option.CorssCursorInfo.VPenType>0) chart.ChartCorssCursor.VPenType=option.CorssCursorInfo.VPenType;
+ }
+
+ //保存十字光标文字高度
+ option.CorssCursor={};
+ option.CorssCursor.TitleHeight=chart.ChartCorssCursor.TextHeight;
+
+ if (option.Frame)
+ {
+ for(var i=0;i0) chart.Frame.SubFrame[i].Height = item.Height;
+
+ if (item.IsShowLeftText==false) chart.Frame.SubFrame[i].Frame.YSplitOperator.IsShowLeftText=item.IsShowLeftText; //显示左边刻度
+ if (item.IsShowRightText==false) chart.Frame.SubFrame[i].Frame.YSplitOperator.IsShowRightText=item.IsShowRightText; //显示右边刻度
+ }
+ }
+
+ if (option.KLine)
+ {
+ if (option.KLine.ShowKLine == false) chart.ChartPaint[0].IsShow = false;
+ if (option.KLine.InfoPosition>0) chart.ChartPaint[0].InfoPosition=option.KLine.InfoPosition;
+ if (option.KLine.IsShowMaxMinPrice == false) chart.ChartPaint[0].IsShowMaxMinPrice=option.KLine.IsShowMaxMinPrice;
+ }
+
+ if(option.KLineTitle) //股票名称 日期 周期
+ {
+ if(option.KLineTitle.IsShowName==false) chart.TitlePaint[0].IsShowName=false;
+ if(option.KLineTitle.IsShowSettingInfo==false) chart.TitlePaint[0].IsShowSettingInfo=false;
+ if(option.KLineTitle.IsShow == false) chart.TitlePaint[0].IsShow = false;
+ }
+
+ if (option.ExtendChart)
+ {
+ for(var i=0;i0) chart.ZoomStepPixel=option.ZoomStepPixel;
+
+ chart.Create(option.Listener);
+
+ if (option.Border)
+ {
+ if (IFrameSplitOperator.IsNumber(option.Border.Left)) chart.Frame.ChartBorder.Left=option.Border.Left;
+ else option.Border.Left=chart.Frame.ChartBorder.Left;
+ if (IFrameSplitOperator.IsNumber(option.Border.Right)) chart.Frame.ChartBorder.Right=option.Border.Right;
+ else option.Border.Right=chart.Frame.ChartBorder.Right;
+ if (IFrameSplitOperator.IsNumber(option.Border.Top)) chart.Frame.ChartBorder.Top=option.Border.Top;
+ else option.Border.Top=chart.Frame.ChartBorder.Top;
+ if (IFrameSplitOperator.IsNumber(option.Border.Bottom)) chart.Frame.ChartBorder.Bottom=option.Border.Bottom;
+ else option.Border.Bottom=chart.Frame.ChartBorder.Bottom;
+ }
+
+ this.AdjustChartBorder(chart);
+
+ if (option.CorssCursorTouchEnd===true) chart.CorssCursorTouchEnd = option.CorssCursorTouchEnd;
+
+ if (option.CorssCursorInfo)
+ {
+ var item=option.CorssCursorInfo;
+ if (IFrameSplitOperator.IsNumber(item.HPenType)) chart.ChartCorssCursor.HPenType=item.HPenType;
+ if (IFrameSplitOperator.IsNumber(item.VPenType)) chart.ChartCorssCursor.VPenType=item.VPenType;
+ if (IFrameSplitOperator.IsBool(item.IsShowTooltip)) chart.ChartCorssCursor.IsShowTooltip=item.IsShowTooltip;
+ }
+
+ if (option.Frame)
+ {
+ var item=option.Frame
+ if (item.SplitCount) chart.Frame.YSplitOperator.SplitCount=item.SplitCount;
+ if (IFrameSplitOperator.IsNumber(item.SplitType)) chart.Frame.YSplitOperator.SplitType=item.SplitType;
+ if (IFrameSplitOperator.IsNumber(item.Height)) chart.Frame.Height = item.Height;
+ if (IFrameSplitOperator.IsNumber(item.YLineType)) chart.Frame.YSplitOperator.LineType=item.YLineType;
+ if (IFrameSplitOperator.IsNumber(item.XLineType)) chart.Frame.XSplitOperator.LineType=item.XLineType;
+ if (Array.isArray(item.IgnoreYValue)) chart.Frame.YSplitOperator.IgnoreYValue=item.IgnoreYValue;
+ if (item.IsShowLeftText===false || item.IsShowLeftText===true)
+ {
+ chart.Frame.IsShowYText[0]=item.IsShowLeftText;
+ chart.Frame.YSplitOperator.IsShowLeftText=item.IsShowLeftText; //显示左边刻度
+ }
+ if (item.IsShowRightText===false || item.IsShowRightText===true)
+ {
+ chart.Frame.IsShowYText[1]=item.IsShowRightText;
+ chart.Frame.YSplitOperator.IsShowRightText=item.IsShowRightText; //显示右边刻度
+ }
+
+ if (item.IsShowXLine==false) chart.Frame.IsShowXLine=item.IsShowXLine;
+ if (item.IsShowYLine==false) chart.Frame.IsShowYLine=item.IsShowYLine;
+ }
+
+ return chart;
+ }
+
+ //根据option内容绘制图形
+ this.SetOption=function(option)
+ {
+ var chart=null;
+ switch(option.Type)
+ {
+ case "历史K线图":
+ case '历史K线图横屏':
+ chart=this.CreateKLineChartContainer(option);
+ break;
+ case "自定义指数历史K线图":
+ chart=this.CreateCustomKLineChartContainer(option);
+ break;
+ case "分钟走势图":
+ case "分钟走势图横屏":
+ chart=this.CreateMinuteChartContainer(option);
+ break;
+ case "历史分钟走势图":
+ chart=this.CreateHistoryMinuteChartContainer(option);
+ break;
+ case 'K线训练':
+ case 'K线训练横屏':
+ chart=this.CreateKLineTrainChartContainer(option);
+ break;
+ case "深度图":
+ chart=this.CreateDepthChartContainer(option);
+ break;
+ case "简单图形":
+ return this.CreateSimpleChart(option);
+ case "饼图":
+ case '雷达图':
+ return this.CreatePieChart(option);
+ case '地图':
+ return this.CreateMapChart(option);
+ default:
+ return false;
+ }
+
+ if (!chart) return false;
+
+ if (option.OnCreatedCallback) option.OnCreatedCallback(chart);
+
+ //是否自动更新
+ if (option.IsAutoUpdate!=null) chart.IsAutoUpdate=option.IsAutoUpdate;
+ if (option.AutoUpdateFrequency>0) chart.AutoUpdateFrequency=option.AutoUpdateFrequency;
+ //注册事件
+ if (option.EventCallback)
+ {
+ for(var i=0;i0)
+ {
+ var item=this.Start[this.Start.length-1];
+ var spanTime=time-item.Time;
+ if (spanTime>0 && spanTime<300)
+ {
+ this.Start.push({ X:x, Y:y, Time:time });
+ }
+ else
+ {
+ this.Start=[];
+ }
+ }
+ else
+ {
+ this.Start.push({ X:x, Y:y, Time:time });
+ }
+ }
+
+ this.IsVaildDBClick=function()
+ {
+ if (this.Start.length==2) return true;
+
+ return false;
+ }
+
+ this.AddTouchEnd=function(time)
+ {
+ if (this.Start.length<=0) return;
+
+ var item=this.Start[this.Start.length-1];
+ var spanTime=time-item.Time;
+ if (spanTime>=0 && spanTime<150)
+ {
+
+ }
+ else
+ {
+ this.Start=[];
+ }
+ }
+}
+
+/*
+ 图形控件
+*/
+function JSChartContainer(uielement, OffscreenElement)
+{
+ this.ClassName='JSChartContainer';
+ var _self = this;
+ this.Frame; //框架画法
+ this.ChartPaint=new Array(); //图形画法
+ this.ChartPaintEx=[]; //图形扩展画法
+ this.ChartInfo=new Array(); //K线|走势图上信息地雷
+ this.ChartInfoPaint; //信息地理
+ this.ExtendChartPaint=new Array(); //扩展画法
+ this.TitlePaint=new Array(); //标题画法
+ this.OverlayChartPaint=new Array(); //叠加信息画法
+ this.ChartDrawPicture=new Array(); //画图工具
+ this.ChartDrawStorage; //画图工具保存
+ this.ChartDrawOption={ IsLockScreen:false, Zoom:5 }; //画图工具设置 { IsLockScreen://是否锁住屏幕, Zoom: //线段|点放大倍数 }
+ this.CurrentChartDrawPicture=null; //当前的画图工具
+ this.SelectChartDrawPicture=null; //当前选中的画图
+ this.EnableShowCorssCursor={ DrawPicture:true }; //DrawPicture=画图是否显示十字光标
+ this.ChartPictureMenu; //画图工具 单个图形设置菜单
+ this.ChartCorssCursor; //十字光标
+ this.IsClickShowCorssCursor=false; //手势点击显示十字光标
+ this.ChartSplashPaint=null; //等待提示
+ this.LoadDataSplashTitle="数据加载中"; //下载数据提示信息
+ if (OffscreenElement)
+ {
+ this.Canvas=OffscreenElement.getContext("2d");
+ this.OffscreenCanvasElement=OffscreenElement;
+
+ this.ShowCanvas=uielement.getContext("2d");
+ }
+ else
+ {
+ this.Canvas=uielement.getContext("2d"); //画布
+ this.ShowCanvas=null;
+ }
+
+ this.UIElement=uielement;
+ this.MouseDrag;
+ this.PhoneTouchInfo; //手机手势信息
+ this.DragMode=1; //拖拽模式 0 禁止拖拽 1 数据拖拽 2 区间选择 3(CLICK_TOUCH_MODE_ID)=长按十字光标显示保留/点击十字光标消失 (使用TouchStatus)
+ this.EnableBorderDrag=true; //是否可以拖拽边框调整指标框高度
+ this.BorderDrag; //{ Index:, }
+ this.YDrag; //{Index: } //y轴拖拽放大缩小
+ this.TouchStatus={ CorssCursorShow:false }, //十字光标是否显示
+ this.DragTimer;
+ this.EnableScrollUpDown=false; //是否可以上下滚动图形(手机端才有)
+ this.ClickChartTimer=null; //点击图形定时器,解决双击和单击K线事件
+
+ this.CursorIndex=0; //十字光标X轴索引
+ this.LastPoint=new Point(); //鼠标位置
+ this.IsForceLandscape=false; //是否强制横屏
+ this.CorssCursorTouchEnd = false; //手离开屏幕自动隐藏十字光标
+ this.IsTitleShowLatestData=false; //十字/手势不在K线图上,标题显示最新一个数据
+ this.StepPixel=4; //移动一个数据需要的像素 0=自动模式(根据K线宽度+间距)
+ this.ZoomStepPixel=5; //放大缩小手势需要的最小像素
+ this.TouchMoveMinAngle=70; //左右移动最小角度
+ this.EnableAnimation=false; //是否开启动画
+
+ //tooltip提示信息
+ this.Tooltip=document.createElement("div");
+ this.Tooltip.className='jschart-tooltip';
+ this.Tooltip.style.background=g_JSChartResource.TooltipBGColor;
+ this.Tooltip.style.opacity=g_JSChartResource.TooltipAlpha;
+ this.Tooltip.style["pointer-events"]="none";
+ this.Tooltip.id=Guid();
+ uielement.parentNode.appendChild(this.Tooltip);
+ this.IsShowTooltip=true; //是否显示K线tooltip
+
+ //区间选择
+ this.SelectRect=document.createElement("div");
+ this.SelectRect.className="jschart-selectrect";
+ this.SelectRect.style.background=g_JSChartResource.SelectRectBGColor;
+ this.SelectRect.style["pointer-events"]="none";
+ //this.SelectRect.style.opacity=g_JSChartResource.SelectRectAlpha;
+ this.SelectRect.id=Guid();
+ this.SelectRect.oncontextmenu=function() { return false; }; //屏蔽选中区域系统右键菜单
+ uielement.parentNode.appendChild(this.SelectRect);
+
+ //区间选择右键菜单
+ this.SelectRectRightMenu;
+
+ //坐标轴风格方法 double-更加数值型分割 price-更加股票价格分割
+ this.FrameSplitData=new Map();
+ this.FrameSplitData.set("double",new SplitData());
+ this.FrameSplitData.set("price",new PriceSplitData());
+
+ //事件回调
+ this.mapEvent=new Map(); //通知外部调用 key:JSCHART_EVENT_ID value:{Callback:回调,}
+
+ this.IsOnTouch = false; //是否再操作数据
+ this.TouchDrawCount = 0; //手势绘制次数
+ this.DisableMouse=false; //禁止鼠标事件
+ this.LanguageID=JSCHART_LANGUAGE_ID.LANGUAGE_CHINESE_ID;
+ this.PressTime=500;
+
+ this.NetworkFilter; //网络请求回调 function(data, callback);
+ this.LastMouseStatus={ }
+ this.ClickDownPoint; //鼠标点击坐标 {X, Y}, 鼠标放开以后清空为null
+ this.IsDestroy=false; //是否已经销毁了
+
+ this.EnableYDrag={ Left:false, Right:false }; //是否可以拖拽Y轴,放大缩小Y轴最大最小值
+ this.EnableZoomIndexWindow=false; //是否支持双击缩放附图窗口
+
+ this.PhoneDBClick=new PhoneDBClick();
+
+ this.ChartDestory=function() //销毁
+ {
+ this.IsDestroy=true;
+ this.StopAutoUpdate();
+
+ if (this.GetLatestVersionTimer!=null)
+ {
+ clearTimeout(this.GetLatestVersionTimer);
+ this.GetLatestVersionTimer=null;
+ }
+ }
+
+
+ this.GetLatestVersionTimer=null; //获取最新版本
+ this.GetLatestVersion=function()
+ {
+ var waittimer=1000*60*3.5;
+ var value="aHR0cHM6Ly9ocWNoYXJ0LnplYWxpbmsuY29tL2FwaS9HZXRWZXJzaW9u";
+ JSConsole.Chart.Log("[JSChartContainer::GetLatestVersion] wait for get hqchart latest version. ",waittimer);
+ this.GetLatestVersionTimer = setTimeout(()=>
+ {
+ var width=0, height=0;
+ if (this.Frame && this.Frame.ChartBorder)
+ {
+ width=this.Frame.ChartBorder.GetChartWidth();
+ height=this.Frame.ChartBorder.GetChartHeight();
+ }
+
+ var url=`${atob(value)}?width=${width}&height=${height}&type=h5`;
+
+ JSNetwork.HttpRequest({
+ url: url,
+ type:"get",
+ dataType: "json",
+ async:true,
+ success:function(data)
+ {
+ JSConsole.Chart.Log("[JSChartContainer::GetLatestVersion] hqchart latest version. ",data);
+ //TODO:判断是否是最新版本
+ },
+ error:function(request, textStatus, errorThrown)
+ {
+ JSConsole.Chart.Log("[JSChartContainer::GetLatestVersion] Get HQChart latest version failed.", request);
+ }
+ });
+
+ }, waittimer);
+ }
+
+ //设置事件回调
+ //{event:事件id, callback:回调函数}
+ this.AddEventCallback=function(object)
+ {
+ if (!object || !object.event || !object.callback) return;
+
+ var data={Callback:object.callback, Source:object};
+ this.mapEvent.set(object.event,data);
+ }
+
+ this.RemoveEventCallback=function(eventid)
+ {
+ if (!this.mapEvent.has(eventid)) return;
+
+ this.mapEvent.delete(eventid);
+ }
+
+ this.GetEventCallback=function(id) //获取事件回调
+ {
+ if (!this.mapEvent.has(id)) return null;
+ var item=this.mapEvent.get(id);
+ return item;
+ }
+
+ //接收指标数据
+ this.GetIndexEvent=function()
+ {
+ return this.GetEventCallback(JSCHART_EVENT_ID.RECV_INDEX_DATA);
+ }
+
+ this.GetOverlayIndexEvent=function()
+ {
+ return this.GetEventCallback(JSCHART_EVENT_ID.RECV_OVERLAY_INDEX_DATA);
+ }
+
+ //鼠标事件绑定
+ uielement.onmousemove=(e)=>{ this.UIOnMouseMove(e);}
+ uielement.oncontextmenu=(e)=> { return this.UIOnContextMenu(e); }
+ uielement.ondblclick=(e)=>{ this.UIOnDblClick(e); }
+ uielement.onmousedown=(e)=> { this.UIOnMouseDown(e); }
+ uielement.onmouseout=(e)=>{ this.UIOnMounseOut(e); }
+
+ this.UIOnMouseMove=function(e)
+ {
+ //JSConsole.Chart.Log('[JSChartContainer.UIOnMouseMove] e.clientX, e.clientY, left, top ',e.clientX, e.clientY, this.getBoundingClientRect().left,this.getBoundingClientRect().top);
+ var pixelTatio = GetDevicePixelRatio(); //鼠标移动坐标是原始坐标 需要乘以放大倍速
+ var x = (e.clientX-this.UIElement.getBoundingClientRect().left)*pixelTatio;
+ var y = (e.clientY-this.UIElement.getBoundingClientRect().top)*pixelTatio;
+
+ //加载数据中,禁用鼠标事件
+ if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return;
+ if (this.DisableMouse==true) return;
+ if (this.BorderDrag) return;
+ if (this.YDrag) return;
+
+ //保存最后一次鼠标移动信息
+ var MoveStatus={ X:x, Y:y, IsInClient: this.IsMouseOnClient(x,y) };
+ this.LastMouseStatus.OnMouseMove=MoveStatus;
+ //JSConsole.Chart.Log("[JSChartContainer::UIOnMouseMove] MoveStatus", MoveStatus);
+
+ this.OnMouseMove(x,y,e);
+ }
+
+ this.IsMouseOnClient=function(x,y)
+ {
+ var isInClient=false;
+ this.Canvas.beginPath();
+ this.Canvas.rect(this.Frame.ChartBorder.GetLeft(),this.Frame.ChartBorder.GetTop(),this.Frame.ChartBorder.GetWidth(),this.Frame.ChartBorder.GetHeight());
+ isInClient=this.Canvas.isPointInPath(x,y);
+ return isInClient;
+ }
+
+ this.UIOnContextMenu=function(e)
+ {
+ if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return;
+
+ var x = e.clientX-this.UIElement.getBoundingClientRect().left;
+ var y = e.clientY-this.UIElement.getBoundingClientRect().top;
+
+ if(typeof(this.OnRightMenu)=='function') this.OnRightMenu(x,y,e); //右键菜单事件
+
+ return false;
+ }
+
+ this.UIOnDblClick=function(e)
+ {
+ var pixelTatio = GetDevicePixelRatio();
+ var x = (e.clientX-this.UIElement.getBoundingClientRect().left)*pixelTatio;
+ var y = (e.clientY-this.UIElement.getBoundingClientRect().top)*pixelTatio;
+ this.OnDoubleClick(x,y,e);
+ }
+
+ //是否在拖拽Y轴上
+ this.TryYDrag=function(x,y)
+ {
+ if (!this.EnableYDrag) return null;
+ if (!this.EnableYDrag.Left && !this.EnableYDrag.Right) return null;
+ if (!this.Frame || !this.Frame.PtInFrameY) return null;
+
+ var dragY=this.Frame.PtInFrameY(x,y);
+ if (!dragY || dragY.Index<0) return null;
+
+ if (dragY.Left && this.EnableYDrag.Left && this.Frame.IsEnableDragY(dragY.Index))
+ {
+ return dragY;
+ }
+
+ if (dragY.Right && this.EnableYDrag.Right && this.Frame.IsEnableDragY(dragY.Index))
+ {
+ return dragY;
+ }
+
+ return null;
+ }
+
+ //是否可以上下拖拽
+ this.TryUpDownDrag=function(x,y)
+ {
+ var windowIndex=this.Frame.PtInFrame(x,y);
+ if (windowIndex<0) return null;
+
+ var item=this.Frame.SubFrame[windowIndex];
+ if (!item || !item.Frame) return null;
+
+ var frame=item.Frame;
+ if (!frame.YSplitOperator || !frame.YSplitOperator.FixedYMaxMin) return null;
+
+ return { Index:windowIndex, X:x, Y:y };
+ }
+
+ this.TryRectSelectDrag=function(x,y)
+ {
+ var paint=this.GetRectSelectPaint();
+ if (!paint) return null;
+ if (paint.GetPointCount()<=0) return null;
+
+ var item=paint.PtInPaint(x,y);
+
+ return { Item:item, X:x, Y:y };
+ }
+
+ this.UIOnMouseDown=function(e)
+ {
+ if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return;
+
+ this.ClickDownPoint={ X:e.clientX, Y:e.clientY };
+ this.IsOnTouch=true;
+ this.BorderDrag=null;
+ this.YDrag=null;
+ this.UpDownDrag=null;
+ this.RectSelectDrag=null;
+
+ var pixelTatio = GetDevicePixelRatio();
+ var x = (e.clientX-this.UIElement.getBoundingClientRect().left)*pixelTatio;
+ var y = (e.clientY-this.UIElement.getBoundingClientRect().top)*pixelTatio;
+
+ var button=this.Frame.PtInButtons(x,y);
+ if (button && this.ClickFrameButton)
+ {
+ this.ClickFrameButton(button);
+ return;
+ }
+
+ if (this.TryClickLock)
+ {
+ //JSConsole.Chart.Log('[uielement.onmousedown] left, top ',e.clientX, e.clientY, this.getBoundingClientRect().left,this.getBoundingClientRect().top);
+ if (this.TryClickLock(x,y)) return;
+ }
+
+ this.HideSelectRect();
+ if (this.SelectRectRightMenu) this.SelectRectRightMenu.Hide();
+ if (this.ChartPictureMenu) this.ChartPictureMenu.Hide();
+
+ var paint=this.GetRectSelectPaint();
+ if (paint && paint.GetPointCount()>0)
+ {
+ var item=paint.PtInPaint(x,y);
+ if (item)
+ {
+ this.UIElement.style.cursor="ew-resize";
+ this.RectSelectDrag={ Index:item.PointIndex };
+ JSConsole.Chart.Log("[JSChartContainer::UIOnMouseDown] drag rect select ",item);
+ }
+ }
+
+ if (!this.RectSelectDrag && this.ClearRectSelect(false)) this.Draw();
+
+ if (this.EnableBorderDrag && this.Frame)
+ {
+ var dragBorder=this.Frame.PtInFrameBorder(x,y);
+ if (dragBorder && dragBorder.Index>=0)
+ {
+ this.UIElement.style.cursor="n-resize";
+ this.BorderDrag={ Index:dragBorder.Index };
+ JSConsole.Chart.Log("[JSChartContainer::UIOnMouseDown] DragBorder ",dragBorder);
+ }
+ }
+
+ //拖拽Y轴缩放
+ if (!this.BorderDrag)
+ {
+ var dragY=this.TryYDrag(x,y);
+ if (dragY)
+ {
+ this.UIElement.style.cursor=dragY.Position==0 ? "n-resize":"row-resize";
+ this.YDrag=dragY;
+ JSConsole.Chart.Log("[JSChartContainer::UIOnMouseDown] dragY ",dragY);
+ }
+ else
+ {
+ var dragUpDown=this.TryUpDownDrag(x,y);
+ if (dragUpDown)
+ {
+ this.UIElement.style.cursor="pointer";
+ this.UpDownDrag=dragUpDown;
+ JSConsole.Chart.Log("[JSChartContainer::UIOnMouseDown] dragUpDown ",dragUpDown);
+ }
+ }
+ }
+
+ if(this.DragMode==0) return;
+
+ var drag=
+ {
+ "Click":{},
+ "LastMove":{} //最后移动的位置
+ };
+
+ drag.Click.X=e.clientX;
+ drag.Click.Y=e.clientY;
+ drag.LastMove.X=e.clientX;
+ drag.LastMove.Y=e.clientY;
+
+ this.MouseDrag=drag;
+ this.SelectChartDrawPicture=null;
+
+ if (this.BorderDrag)
+ {
+
+ }
+ else if (this.YDrag || this.UpDownDrag || this.RectSelectDrag)
+ {
+
+ }
+ else if (this.CurrentChartDrawPicture) //画图工具模式
+ {
+ var drawPicture=this.CurrentChartDrawPicture;
+ if (drawPicture.Status==2)
+ this.SetChartDrawPictureThirdPoint(drag.Click.X,drag.Click.Y);
+ else
+ {
+ this.SetChartDrawPictureFirstPoint(drag.Click.X,drag.Click.Y);
+ //只有1个点 直接完成
+ if (this.FinishChartDrawPicturePoint()) this.DrawDynamicInfo();
+ }
+ }
+ else //是否在画图工具上
+ {
+ var drawPictrueData={};
+ drawPictrueData.X=(e.clientX-this.UIElement.getBoundingClientRect().left)*pixelTatio;
+ drawPictrueData.Y=(e.clientY-this.UIElement.getBoundingClientRect().top)*pixelTatio;
+ if (this.GetChartDrawPictureByPoint(drawPictrueData))
+ {
+ if (drawPictrueData.ChartDrawPicture.EnableMove==true)
+ {
+ drawPictrueData.ChartDrawPicture.Status=20;
+ drawPictrueData.ChartDrawPicture.ValueToPoint();
+ drawPictrueData.ChartDrawPicture.MovePointIndex=drawPictrueData.PointIndex;
+ this.CurrentChartDrawPicture=drawPictrueData.ChartDrawPicture;
+ this.SelectChartDrawPicture=drawPictrueData.ChartDrawPicture;
+ }
+ else
+ {
+ this.CurrentChartDrawPicture=null;
+ this.SelectChartDrawPicture=null;
+ }
+
+ var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CLICK_DRAWPICTURE); //选中画图工具事件
+ if (event && event.Callback)
+ {
+ var sendData={ DrawPicture: drawPictrueData.ChartDrawPicture };
+ event.Callback(event,sendData,this);
+ }
+ else
+ {
+ this.OnSelectChartPicture(drawPictrueData.ChartDrawPicture); //选中画图工具事件
+ }
+ }
+ else
+ {
+ if (this.ClickChartTimer!=null)
+ {
+ clearTimeout(this.ClickChartTimer);
+ this.ClickChartTimer=null;
+ }
+
+ var self=this;
+ var ptClick={ X:this.ClickDownPoint.X, Y:this.ClickDownPoint.Y };
+ this.ClickChartTimer = setTimeout(function()
+ {
+ self.TryClickPaintEvent(JSCHART_EVENT_ID.ON_CLICK_CHART_PAINT,ptClick,e);
+ }, 250);
+
+ }
+ }
+
+ document.onmousemove=(e)=>{ this.DocOnMouseMove(e); }
+ document.onmouseup=(e)=> { this.DocOnMouseUp(e); }
+ }
+
+ this.DocOnMouseMove=function(e)
+ {
+ //加载数据中,禁用鼠标事件
+ if (this.ChartSplashPaint && this.IsEnableSplash == true) return;
+
+ var drag=this.MouseDrag;
+ if (!drag) return;
+
+ var moveSetp=Math.abs(drag.LastMove.X-e.clientX);
+ var moveSetpY=Math.abs(drag.LastMove.Y-e.clientY);
+ var isDragSelectRect=(this.RectSelectDrag && this.RectSelectDrag.Index>=0);
+
+ if (this.BorderDrag && this.BorderDrag.Index>=0)
+ {
+ if(Math.abs(drag.LastMove.Y-e.clientY)<5) return;
+
+ var yMove=e.clientY-drag.LastMove.Y;
+
+ this.OnMoveFromeBorder(this.BorderDrag.Index, yMove);
+
+ drag.LastMove.X=e.clientX;
+ drag.LastMove.Y=e.clientY;
+ }
+ else if (this.YDrag && this.YDrag.Index>=0)
+ {
+ if(moveSetpY<5) return;
+
+ var yMove=e.clientY-drag.LastMove.Y;
+
+ //this.UIElement.style.cursor="n-resize";
+
+ JSConsole.Chart.Log("[JSChartContainer::DocOnMouseMove] YDrag ",this.YDrag,yMove);
+ this.OnZoomUpDownFrameY(this.YDrag, yMove);
+
+ drag.LastMove.X=e.clientX;
+ drag.LastMove.Y=e.clientY;
+ }
+ else if (this.CurrentChartDrawPicture)
+ {
+ var drawPicture=this.CurrentChartDrawPicture;
+ if (drawPicture.Status==1 || drawPicture.Status==2)
+ {
+ if(Math.abs(drag.LastMove.X-e.clientX)<5 && Math.abs(drag.LastMove.Y-e.clientY)<5) return;
+ if(this.SetChartDrawPictureSecondPoint(e.clientX,e.clientY))
+ {
+ this.DrawDynamicInfo();
+ }
+ }
+ else if (drawPicture.Status==3)
+ {
+ if(this.SetChartDrawPictureThirdPoint(e.clientX,e.clientY))
+ {
+ this.DrawDynamicInfo();
+ }
+ }
+ else if (drawPicture.Status==20) //画图工具移动
+ {
+ if(Math.abs(drag.LastMove.X-e.clientX)<5 && Math.abs(drag.LastMove.Y-e.clientY)<5) return;
+
+ if(this.MoveChartDrawPicture(e.clientX-drag.LastMove.X,e.clientY-drag.LastMove.Y))
+ {
+ this.DrawDynamicInfo();
+ }
+ }
+
+ drag.LastMove.X=e.clientX;
+ drag.LastMove.Y=e.clientY;
+ }
+ else if (this.DragMode==1 || isDragSelectRect) //数据上下左右拖拽
+ {
+ this.OnDragMode_One({X:moveSetp, Y:moveSetpY}, e);
+ }
+ else if (this.DragMode==2) //区间选择
+ {
+ var yMoveSetp=Math.abs(drag.LastMove.Y-e.clientY);
+
+ if (moveSetp<5 && yMoveSetp<5) return;
+
+ this.UIElement.style.cursor="default";
+
+ var x=drag.Click.X-uielement.getBoundingClientRect().left;
+ var y=drag.Click.Y-uielement.getBoundingClientRect().top;
+ var x2=e.clientX-uielement.getBoundingClientRect().left;
+ var y2=e.clientY-uielement.getBoundingClientRect().top;
+ this.ShowSelectRect(x,y,x2,y2);
+
+ drag.LastMove.X=e.clientX;
+ drag.LastMove.Y=e.clientY;
+
+ }
+ }
+
+ this.OnDragMode_One=function(moveData, e)
+ {
+ var moveSetp=moveData.X;
+ var moveSetpY=moveData.Y;
+ var drag=this.MouseDrag;
+
+ if (moveSetp<5 && moveSetpY<5) return;
+
+ var bNeedDraw=false;
+ var bUpDownY=false;
+ if (moveSetpY>=5)
+ {
+ if (this.UpDownDrag && this.UpDownDrag.Index>=0)
+ {
+ var yMove=e.clientY-drag.LastMove.Y;
+ JSConsole.Chart.Log("[JSChartContainer::OnDragMode_One] UpDownDrag ",this.UpDownDrag,yMove);
+ this.UIElement.style.cursor="pointer";
+ if (this.OnUpDonwFrameY(this.UpDownDrag, yMove))
+ {
+ bNeedDraw=true;
+ bUpDownY=true;
+ }
+ drag.LastMove.Y=e.clientY;
+ }
+ }
+
+ if (moveSetp>=5)
+ {
+ var isLeft=true;
+ if (drag.LastMove.X=0)
+ {
+ var obj={ X:e.clientX, Y:e.clientY, PointIndex:this.RectSelectDrag.Index, Name:"MoveRectSelectLine" };
+ if (this.MoveRectSelectPoint(obj)) bNeedDraw=true;
+ }
+ else
+ {
+ this.UIElement.style.cursor="pointer";
+ var oneStepWidth=this.GetMoveOneStepWidth();
+ if (moveSetp=0);
+ var bClearDrawPicture=true;
+ if (this.CurrentChartDrawPicture)
+ {
+ var drawPicture=this.CurrentChartDrawPicture;
+ if (drawPicture.Status==2 || drawPicture.Status==1 || drawPicture.Status==3)
+ {
+ drawPicture.PointStatus=drawPicture.Status;
+ if (this.FinishChartDrawPicturePoint())
+ this.DrawDynamicInfo();
+ else
+ bClearDrawPicture=false;
+ }
+ else if (drawPicture.Status==20)
+ {
+ if (this.FinishMoveChartDrawPicture())
+ this.DrawDynamicInfo();
+ }
+ }
+ else if (isDragSelectRect) //区间选择拖动范围
+ {
+ if (this.OnDragSelectRectMouseUp) this.OnDragSelectRectMouseUp(e);
+ }
+ else if (IsMinuteChart)
+ {
+ if (this.OnMinuteSelectRectMouseUp) this.OnMinuteSelectRectMouseUp(e);
+ }
+ else if (this.DragMode==2) //区间选择
+ {
+ var drag=this.MouseDrag;
+ drag.LastMove.X=e.clientX;
+ drag.LastMove.Y=e.clientY;
+
+ var selectData=new SelectRectData();
+ var pixelTatio = GetDevicePixelRatio();
+ //区间起始位置 结束位子
+ selectData.XStart=(drag.Click.X-uielement.getBoundingClientRect().left)*pixelTatio;
+ selectData.YStart=(drag.Click.Y-uielement.getBoundingClientRect().top)*pixelTatio;
+ selectData.XEnd=(drag.LastMove.X-uielement.getBoundingClientRect().left)*pixelTatio;
+ selectData.YEnd=(drag.LastMove.Y-uielement.getBoundingClientRect().top)*pixelTatio;
+ selectData.JSChartContainer=this;
+ selectData.Stock={Symbol:this.Symbol, Name:this.Name};
+
+ if (!this.BorderDrag && this.GetSelectRectData(selectData))
+ {
+ var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_SELECT_RECT);
+ var paint=this.GetRectSelectPaint();
+ if (event && event.Callback)
+ {
+ var data=
+ {
+ X:drag.LastMove.X-uielement.getBoundingClientRect().left,
+ Y:drag.LastMove.Y-uielement.getBoundingClientRect().top,
+ SelectData:selectData, //区间选择的数据
+ RectSelectPaint:paint //区间选择背景
+ };
+ event.Callback(event,data,this);
+ }
+
+ if (IsMinuteChart) //分时图直接显示显示区间选择
+ {
+ this.HideSelectRect();
+ this.UpdateSelectRect(selectData.Start,selectData.End);
+ }
+ else
+ {
+ if (this.SelectRectRightMenu)
+ {
+ e.data=
+ {
+ Chart:this,
+ X:drag.LastMove.X-uielement.getBoundingClientRect().left,
+ Y:drag.LastMove.Y-uielement.getBoundingClientRect().top,
+ SelectData:selectData, //区间选择的数据
+ RectSelectPaint:paint //区间选择背景
+ };
+ this.SelectRectRightMenu.DoModal(e);
+ }
+ }
+ }
+ else
+ {
+ this.TryClickPaintEvent(JSCHART_EVENT_ID.ON_CLICKUP_CHART_PAINT,this.ClickDownPoint,e);
+ }
+ }
+ else
+ {
+ this.TryClickPaintEvent(JSCHART_EVENT_ID.ON_CLICKUP_CHART_PAINT,this.ClickDownPoint,e);
+ this.ClickEvent(e);
+ }
+
+ //清空数据
+ JSConsole.Chart.Log('[KLineChartContainer::document.onmouseup]',e);
+ this.UIElement.style.cursor="default";
+ this.MouseDrag=null;
+ this.ClickDownPoint=null;
+ this.IsOnTouch=false;
+ if (this.BorderDrag && this.BorderDrag.Index>=0) this.Frame.SaveSubFrameHeightRate(); //拖拽指标窗口高度以后保存
+ this.BorderDrag=null;
+ this.YDrag=null;
+ this.UpDownDrag=null;
+ this.RectSelectDrag=null;
+ if (bClearDrawPicture===true) this.CurrentChartDrawPicture=null;
+ }
+
+ this.UIOnMounseOut=function(e)
+ {
+ JSConsole.Chart.Log('[KLineChartContainer::UIOnMounseOut]',e);
+ this.UIOnMouseMove(e);
+ }
+
+ //点击事件
+ this.ClickEvent=function(e)
+ {
+ var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CLICK);
+ if (!event || !event.Callback) return false;
+ if (this.ClickDownPoint.X!=e.clientX || this.ClickDownPoint.Y!=e.clientY) return false;
+ var pixelTatio = GetDevicePixelRatio();
+ var x=(e.clientX-uielement.getBoundingClientRect().left)*pixelTatio;
+ var y=(e.clientY-uielement.getBoundingClientRect().top)*pixelTatio;
+ var data= { X:e.clientX, Y:e.clientY, FrameID:-1 };
+
+ var isInClient=false;
+ this.Canvas.beginPath();
+ this.Canvas.rect(this.Frame.ChartBorder.GetLeft(),this.Frame.ChartBorder.GetTop(),this.Frame.ChartBorder.GetWidth(),this.Frame.ChartBorder.GetHeight());
+ isInClient=this.Canvas.isPointInPath(x,y);
+ if (isInClient)
+ {
+ var yValueExtend={};
+ var yValue=this.Frame.GetYData(y,yValueExtend);
+
+ if (IFrameSplitOperator.IsNumber(yValueExtend.FrameID) && yValueExtend.FrameID>=0)
+ {
+ var xValue=this.Frame.GetXData(x);
+ data.FrameID=yValueExtend.FrameID;
+ data.Data={ X:xValue, Y:yValue } ;
+ }
+ }
+
+ event.Callback(event, data, this);
+ return true;
+ }
+
+ this.PtInChartPaintTooltip=function(x,y, toolTip)
+ {
+ for(var i=0;i { this.OnTouchStart(e); }
+ uielement.ontouchmove=(e)=> {this.OnTouchMove(e); }
+ uielement.ontouchend=(e)=> {this.OnTouchEnd(e); }
+
+ this.AddPhoneDBClickInfo=function(x,y,time)
+ {
+ var item={ X:x, Y:y, Time:time };
+ this.PhoneDBClickInfo.Start.push(item);
+ }
+
+ this.ClearPhoneDBClickInfo=function()
+ {
+ this.PhoneDBClickInfo.Start=[];
+ }
+
+ this.IsShortPhoneClick=function(x,y,time)
+ {
+
+ }
+
+ this.OnTouchStart=function(e)
+ {
+ if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return;
+
+ this.IsOnTouch=true;
+ this.TouchDrawCount=0;
+ this.PhonePinch=null;
+ this.StopDragTimer();
+
+ var isSingleTouch=this.IsSingleTouch(e);
+ if (this.EnableScrollUpDown==false || !isSingleTouch || //多点触屏
+ (this.DragMode==JSCHART_DRAG_ID.CLICK_TOUCH_MODE_ID && this.TouchStatus.CorssCursorShow==true)) //十字光标显示,不能滚动页面
+ {
+ if (e.cancelable) e.preventDefault();
+ }
+
+ if (this.IsPhoneDragging(e))
+ {
+ if (this.TryClickLock || this.TryClickIndexTitle) //指标枷锁区域 , 指标标题点击
+ {
+ var touches = this.GetToucheData(e, this.IsForceLandscape);
+ var pt=this.PointAbsoluteToRelative(touches[0].clientX, touches[0].clientY, true);
+ var x = pt.X;
+ var y = pt.Y;
+ if (this.TryClickLock && this.TryClickLock(x, y)) return;
+ if (this.TryClickIndexTitle && this.TryClickIndexTitle(x,y)) return;
+ }
+
+ var bStartTimer=true;
+ if (this.ChartDrawOption.IsLockScreen)
+ {
+ bStartTimer=false;
+ }
+ else if (this.DragMode==JSCHART_DRAG_ID.CLICK_TOUCH_MODE_ID)
+ {
+ if (this.TouchStatus.CorssCursorShow==true) bStartTimer=false;
+ }
+ else if (this.DragMode==JSCHART_DRAG_ID.DISABLE_DRAG_ID)
+ {
+ bStartTimer=false;
+ }
+ else
+ {
+ if (!isSingleTouch) bStartTimer=false;
+ }
+
+ var drag=
+ {
+ "Click":{},
+ "LastMove":{} //最后移动的位置
+ };
+
+ var touches=this.GetToucheData(e,this.IsForceLandscape);
+
+ drag.Click.X=touches[0].clientX;
+ drag.Click.Y=touches[0].clientY;
+ drag.LastMove.X=touches[0].clientX;
+ drag.LastMove.Y=touches[0].clientY;
+
+ this.MouseDrag=drag;
+ this.PhoneTouchInfo={ Start:{X:touches[0].clientX, Y:touches[0].clientY }, End:{ X:touches[0].clientX, Y:touches[0].clientY } };
+ if (this.SelectChartDrawPicture) this.SelectChartDrawPicture.IsSelected=false;
+ this.SelectChartDrawPicture=null;
+ var isDrawPictrue=false;
+ if (this.CurrentChartDrawPicture) //画图工具模式
+ {
+ var drawPicture=this.CurrentChartDrawPicture;
+ if (drawPicture.Status==2)
+ this.SetChartDrawPictureThirdPoint(drag.Click.X,drag.Click.Y,true);
+ else
+ {
+ this.SetChartDrawPictureFirstPoint(drag.Click.X,drag.Click.Y,true);
+ //只有1个点 直接完成
+ if (this.FinishChartDrawPicturePoint()) this.DrawDynamicInfo({Corss:false, Tooltip:false});
+ }
+
+ if (e.cancelable) e.preventDefault();
+ return;
+ }
+ else
+ {
+ var pt=this.PointAbsoluteToRelative(touches[0].clientX,touches[0].clientY, true);
+ var drawPictrueData={ X:pt.X, Y:pt.Y };
+ var pixelTatio = GetDevicePixelRatio(); //鼠标移动坐标是原始坐标 需要乘以放大倍速
+ if (this.GetChartDrawPictureByPoint(drawPictrueData))
+ {
+ drawPictrueData.ChartDrawPicture.Status=20;
+ drawPictrueData.ChartDrawPicture.ValueToPoint();
+ drawPictrueData.ChartDrawPicture.MovePointIndex=drawPictrueData.PointIndex;
+ drawPictrueData.ChartDrawPicture.IsSelected=true;
+ this.CurrentChartDrawPicture=drawPictrueData.ChartDrawPicture;
+ this.SelectChartDrawPicture=drawPictrueData.ChartDrawPicture;
+ let event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CLICK_DRAWPICTURE); //选中画图工具事件
+ if (event && event.Callback)
+ {
+ let sendData={ DrawPicture: drawPictrueData.ChartDrawPicture };
+ event.Callback(event,sendData,this);
+ }
+
+ if (e.cancelable) e.preventDefault();
+ return;
+ }
+ }
+
+ if (bStartTimer)
+ {
+ //长按2秒,十字光标
+ var self=this;
+ this.DragTimer=setTimeout(function()
+ {
+ if (drag.Click.X==drag.LastMove.X && drag.Click.Y==drag.LastMove.Y) //手指没有移动,出现十字光标
+ {
+ var mouseDrag=self.MouseDrag;
+ self.MouseDrag=null;
+ if (self.DragMode==JSCHART_DRAG_ID.CLICK_TOUCH_MODE_ID) self.TouchStatus.CorssCursorShow=true; //十字显示
+ self.MoveCorssCursor(drag.Click,e);//移动十字光标
+ }
+
+ }, self.PressTime);
+ }
+
+ if (this.EnableZoomIndexWindow)
+ {
+ this.PhoneDBClick.AddTouchStart(touches[0].clientX, touches[0].clientY, Date.now());
+ JSConsole.Chart.Log("[JSChartContainer::OnTouchStart] PhoneDBClick ", this.PhoneDBClick);
+ }
+
+ if (this.ChartDrawOption.IsLockScreen)
+ {
+ this.MouseDrag=null;
+ }
+ else if (this.DragMode==JSCHART_DRAG_ID.CLICK_TOUCH_MODE_ID)
+ {
+
+ }
+ else if (this.DragMode==JSCHART_DRAG_ID.DISABLE_DRAG_ID)
+ {
+ this.MouseDrag=null;
+ this.MoveCorssCursor(drag.Click,e);
+ }
+ else if (this.IsClickShowCorssCursor)
+ {
+ this.MoveCorssCursor(drag.Click,e);
+ }
+
+ this.TouchEvent({ EventID:JSCHART_EVENT_ID.ON_PHONE_TOUCH, FunctionName:"OnTouchStart"}, e);
+ }
+ else if (this.IsPhonePinching(e))
+ {
+ var phonePinch=
+ {
+ "Start":{},
+ "Last":{}
+ };
+
+ var touches=this.GetToucheData(e,this.IsForceLandscape);
+
+ phonePinch.Start={"X":touches[0].pageX,"Y":touches[0].pageY,"X2":touches[1].pageX,"Y2":touches[1].pageY};
+ phonePinch.Last={"X":touches[0].pageX,"Y":touches[0].pageY,"X2":touches[1].pageX,"Y2":touches[1].pageY};
+
+ this.PhonePinch=phonePinch;
+ this.SelectChartDrawPicture=null;
+ }
+ }
+
+ this.OnTouchMove=function(e)
+ {
+ if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return;
+
+ var touches=this.GetToucheData(e,this.IsForceLandscape);
+
+ if (this.IsPhoneDragging(e))
+ {
+ var drag=this.MouseDrag;
+ if (drag==null)
+ {
+ if (this.IsForceLandscape) y=uielement.getBoundingClientRect().width-touches[0].clientY; //强制横屏Y计算
+ if (!this.ChartDrawOption.IsLockScreen) this.MoveCorssCursor({X:touches[0].clientX, Y:touches[0].clientY},e);
+ }
+ else
+ {
+ var moveAngle=this.GetMoveAngle(drag.LastMove,{X:touches[0].clientX, Y:touches[0].clientY});
+ var moveSetp=Math.abs(drag.LastMove.X-touches[0].clientX);
+ var moveUpDown=Math.abs(drag.LastMove.Y-touches[0].clientY);
+ moveSetp=parseInt(moveSetp);
+ var isMoveCorssCursor=(this.DragMode==JSCHART_DRAG_ID.CLICK_TOUCH_MODE_ID && this.TouchStatus.CorssCursorShow==true); //是否移动十字光标
+
+ //JSConsole.Chart.Log("[JSChartContainer::uielement.ontouchmove] moveAngle , moveUpDown", moveAngle,moveUpDown);
+
+ if (this.CurrentChartDrawPicture)
+ {
+ var drawPicture=this.CurrentChartDrawPicture;
+ if (drawPicture.Status==1 || drawPicture.Status==2)
+ {
+ if(moveSetp<5 && moveUpDown<5) return;
+ if(this.SetChartDrawPictureSecondPoint(touches[0].clientX,touches[0].clientY,true))
+ {
+ this.DrawDynamicInfo();
+ }
+ }
+ else if (drawPicture.Status==3)
+ {
+ if(this.SetChartDrawPictureThirdPoint(touches[0].clientX,touches[0].clientY,true))
+ {
+ this.DrawDynamicInfo();
+ }
+ }
+ else if (drawPicture.Status==20) //画图工具移动
+ {
+ if(moveSetp<5 && moveUpDown<5) return;
+
+ if(this.MoveChartDrawPicture(touches[0].clientX-drag.LastMove.X,touches[0].clientY-drag.LastMove.Y,true))
+ {
+ this.DrawDynamicInfo();
+ }
+ }
+
+ drag.LastMove.X=touches[0].clientX;
+ drag.LastMove.Y=touches[0].clientY;
+ }
+ else if (isMoveCorssCursor) //点击模式下 十字光标显示 左右移动十字光标
+ {
+ var mouseDrag=this.MouseDrag;
+ this.MouseDrag=null;
+ this.MoveCorssCursor(drag.Click,e); //移动十字光标
+ }
+ else if (this.DragMode==1 || isMoveCorssCursor==false) //数据左右拖拽
+ {
+ if ( ((moveUpDown>0 && moveSetp<=3) || moveAngle<=this.TouchMoveMinAngle) && this.EnableScrollUpDown==true )
+ {
+ this.StopDragTimer();
+ return;
+ }
+
+ if (moveSetp<5 || moveAngle<=this.TouchMoveMinAngle)
+ {
+ this.PreventTouchEvent(e);
+ return;
+ }
+
+ var isLeft=true;
+ if (drag.LastMove.X0) //放大
+ {
+ var cursorIndex={};
+ cursorIndex.Index=parseInt(Math.abs(this.CursorIndex-0.5).toFixed(0));
+ if (!this.Frame.ZoomUp(cursorIndex)) return;
+ this.CursorIndex=cursorIndex.Index;
+ this.UpdatePointByCursorIndex();
+ this.UpdataDataoffset();
+ this.UpdateFrameMaxMin();
+ this.Draw();
+ this.ShowTooltipByKeyDown();
+ this.StopDragTimer();
+ }
+ else //缩小
+ {
+ var cursorIndex={};
+ cursorIndex.Index=parseInt(Math.abs(this.CursorIndex-0.5).toFixed(0));
+ if (!this.Frame.ZoomDown(cursorIndex)) return;
+ this.CursorIndex=cursorIndex.Index;
+ this.UpdataDataoffset();
+ this.UpdatePointByCursorIndex();
+ this.UpdateFrameMaxMin();
+ this.Draw();
+ this.ShowTooltipByKeyDown();
+ this.StopDragTimer();
+ }
+
+ phonePinch.Last={"X":touches[0].pageX,"Y":touches[0].pageY,"X2":touches[1].pageX,"Y2":touches[1].pageY};
+ }
+
+ this.PreventTouchEvent(e);
+ }
+
+ this.OnTouchEnd=function(e)
+ {
+ JSConsole.Chart.Log('[KLineChartContainer:OnTouchEnd]',e);
+ if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return;
+
+ var bClearDrawPicture=true;
+ if (this.CurrentChartDrawPicture)
+ {
+ var drawPicture=this.CurrentChartDrawPicture;
+ if (drawPicture.Status==2 || drawPicture.Status==1 || drawPicture.Status==3)
+ {
+ drawPicture.PointStatus=drawPicture.Status;
+ if (this.FinishChartDrawPicturePoint())
+ this.DrawDynamicInfo();
+ else
+ bClearDrawPicture=false;
+ }
+ else if (drawPicture.Status==20)
+ {
+ if (this.FinishMoveChartDrawPicture())
+ this.DrawDynamicInfo();
+ }
+ }
+
+ if (this.EnableZoomIndexWindow)
+ {
+ var time=Date.now();
+ this.PhoneDBClick.AddTouchEnd(time);
+ if (this.PhoneDBClick.IsVaildDBClick())
+ {
+ this.OnTouchDBClick(this.PhoneDBClick.Start);
+ this.PhoneDBClick.Clear();
+ }
+ }
+
+ this.IsOnTouch = false;
+ if (bClearDrawPicture===true) this.CurrentChartDrawPicture=null;
+ this.StopDragTimer();
+ this.TouchEvent({ EventID:JSCHART_EVENT_ID.ON_PHONE_TOUCH, FunctionName:"OnTouchEnd"}, e);
+ this.OnTouchFinished();
+ this.TouchDrawCount=0;
+ }
+
+ this.OnTouchDBClick=function(points)
+ {
+ var pt=this.PointAbsoluteToRelative(points[0].X, points[0].Y, true);
+ var x=pt.X, y=pt.Y;
+ JSConsole.Chart.Log(`[KLineChartContainer:OnTouchDBClick] Phone dbclick absolute [${x},${y}], soruce [${points[0].X},${points[0].Y}]`);
+
+ var frameId=this.Frame.PtInFrame(x,y);
+ JSConsole.Chart.Log("[KLineChartContainer::OnTouchDBClick] frameId",frameId);
+ if (frameId>=this.Frame.ZoomStartWindowIndex)
+ {
+ if (this.ZoomIndexWindow(frameId, {X:x, Y:y}))
+ {
+ this.Frame.SetSizeChage(true);
+ this.Draw();
+ return true;
+ }
+ }
+ }
+
+ //手势事件
+ this.TouchEvent=function(obj,e)
+ {
+ var eventID=obj.EventID;
+ var event=this.GetEventCallback(eventID);
+ if (!event || !event.Callback) return false;
+ var drag=this.PhoneTouchInfo
+ if (!drag || !drag.Start || !drag.End ) return false;
+ var pixelTatio = GetDevicePixelRatio();
+ var clientX=drag.End.X/pixelTatio;
+ var clientY=drag.End.Y/pixelTatio;
+ var x=drag.End.X-this.UIElement.getBoundingClientRect().left*pixelTatio;
+ var y=drag.End.Y-this.UIElement.getBoundingClientRect().top*pixelTatio;
+ var data=
+ {
+ X:clientX, Y:clientY, FrameID:-1, FunctionName:obj.FunctionName,
+ Drag:
+ {
+ Start:{ X:drag.Start.X/pixelTatio, Y:drag.Start.Y/pixelTatio },
+ End:{ X:drag.End.X/pixelTatio, Y:drag.End.Y/pixelTatio }
+ }
+ };
+
+ var isInClient=false;
+ this.Canvas.beginPath();
+ this.Canvas.rect(this.Frame.ChartBorder.GetLeft(),this.Frame.ChartBorder.GetTop(),this.Frame.ChartBorder.GetWidth(),this.Frame.ChartBorder.GetHeight());
+ isInClient=this.Canvas.isPointInPath(x,y);
+
+ if (isInClient)
+ {
+ var yValueExtend={};
+ var yValue=this.Frame.GetYData(y,yValueExtend);
+
+ if (IFrameSplitOperator.IsNumber(yValueExtend.FrameID) && yValueExtend.FrameID>=0)
+ {
+ var xValue=this.Frame.GetXData(x);
+ data.FrameID=yValueExtend.FrameID;
+ data.Data={ X:xValue, Y:yValue } ;
+ }
+ }
+
+ event.Callback(event, data, this);
+ return true;
+ }
+
+ this.MoveCorssCursor=function(point,e)
+ {
+ var pixelTatio = GetDevicePixelRatio();
+ var x = point.X-this.UIElement.getBoundingClientRect().left*pixelTatio;
+ var y = point.Y-this.UIElement.getBoundingClientRect().top*pixelTatio;
+ if (this.DragMode==JSCHART_DRAG_ID.CLICK_TOUCH_MODE_ID) this.TouchStatus.CorssCursorShow=true; //十字显示
+ this.OnMouseMove(x,y,e,true);
+ }
+
+ this.DrawEmpty=function()
+ {
+ if (this.UIElement.width<=0 || this.UIElement.height<=0) return;
+ this.Canvas.clearRect(0,0,this.UIElement.width,this.UIElement.height);
+ if (this.Frame)
+ {
+ this.Frame.ScreenImageData=null;
+ this.Frame.Draw();
+ }
+ }
+
+ this.Draw=function()
+ {
+ if (this.ChartCorssCursor) this.ChartCorssCursor.Status=0;
+ if (this.UIElement.width<=0 || this.UIElement.height<=0) return;
+
+ this.Canvas.clearRect(0,0,this.UIElement.width,this.UIElement.height);
+ var pixelTatio = GetDevicePixelRatio(); //获取设备的分辨率
+ this.Canvas.lineWidth=pixelTatio; //手机端需要根据分辨率比调整线段宽度
+
+ if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash)
+ {
+ this.Frame.ClearCoordinateText();
+ this.Frame.Draw( { IsEnableSplash:this.ChartSplashPaint.IsEnableSplash} );
+ this.ChartSplashPaint.Draw();
+ return;
+ }
+
+ //框架
+ this.Frame.SetDrawDepthMap(()=>
+ {
+ for(var i=0;i=0 对应的指标窗口中ID
+ if (option && option.ParentFunction=='OnMouseMove' && option.Point)
+ {
+ ptPosition=this.Frame.PtInFrame(option.Point.X, option.Point.Y);
+ }
+
+ var drawStatus=this.GetDrawStatus();
+ drawStatus.DrawName="DrawDynamicInfo";
+ for(var i=0;i=0) //在K线内部移动,调整K线索引
+ this.CursorIndex=this.Frame.GetXData(x);
+
+ var paint=this.GetRectSelectPaint();
+ if (paint && paint.GetPointCount()>0)
+ {
+ var item=paint.PtInPaint(x,y);
+ if (item)
+ {
+ mouseStatus={ Cursor:"ew-resize", Name:"DragRectSelect"};
+ JSConsole.Chart.Log("[JSChartContainer::OnMouseMove] drag rect select ",item);
+ }
+ }
+
+ if (this.EnableBorderDrag && this.Frame)
+ {
+ var dragBorder=this.Frame.PtInFrameBorder(x,y);
+ if (dragBorder && dragBorder.Index>=0)
+ {
+ mouseStatus={ Cursor:"n-resize", Name:"DragBorder"};
+ JSConsole.Chart.Log("[JSChartContainer::OnMouseMove] drag border ",dragBorder);
+ }
+ }
+
+ if (this.EnableYDrag && this.Frame && !mouseStatus)
+ {
+ var dragY=this.TryYDrag(x,y);
+ if (dragY)
+ {
+ mouseStatus={ Cursor:dragY.Position==0 ? "n-resize":"row-resize", Name:"DragY"};
+ JSConsole.Chart.Log("[JSChartContainer::OnMouseMove] drag y ",dragY);
+ }
+ }
+
+ var button=this.Frame.PtInButtons(x,y);
+ if (button)
+ {
+ mouseStatus={ Cursor:"pointer", Name:"FrameButton"};
+ JSConsole.Chart.Log("[JSChartContainer::OnMouseMove] frame button ", button);
+ }
+
+ var bDrawPicture=false; //是否正在画图
+ if (this.CurrentChartDrawPicture)
+ {
+ if (this.CurrentChartDrawPicture.SetLastPoint) this.CurrentChartDrawPicture.SetLastPoint({X:x,Y:y});
+ bDrawPicture=true;
+ }
+ else
+ {
+ var drawPictrueData={};
+ drawPictrueData.X=x;
+ drawPictrueData.Y=y;
+ if (this.GetChartDrawPictureByPoint(drawPictrueData) &&
+ drawPictrueData.ChartDrawPicture && drawPictrueData.ChartDrawPicture.EnableMove==true)
+ {
+
+ if (drawPictrueData.PointIndex===100) this.UIElement.style.cursor="move";
+ else this.UIElement.style.cursor="pointer";
+ bDrawPicture=true;
+ }
+ else
+ {
+ if (!this.MouseDrag) this.UIElement.style.cursor="default";
+ }
+ }
+
+ var clientPos=this.PtInClient(x,y);
+ var option={ ParentFunction:'OnMouseMove', Point:{X:x, Y:y}, IsPhone:isPhone===true, ClientPos:clientPos };
+ this.DrawDynamicInfo(option);
+ if (mouseStatus) this.UIElement.style.cursor=mouseStatus.Cursor;
+
+ if (this.IsShowTooltip && bDrawPicture==false)
+ {
+ var toolTip=this.GetChartTooltipData(x,y);
+
+ if (toolTip && toolTip.Data)
+ {
+ if (isPhone===true)
+ {
+ var touche=e.touches[0];
+ var xTooltip = touche.clientX-this.UIElement.getBoundingClientRect().left;
+ var yTooltip = touche.clientY-this.UIElement.getBoundingClientRect().top;
+ }
+ else
+ {
+ var xTooltip = e.clientX-this.UIElement.getBoundingClientRect().left;
+ var yTooltip = e.clientY-this.UIElement.getBoundingClientRect().top;
+ }
+ this.ShowTooltip(xTooltip,yTooltip,toolTip);
+ }
+ else
+ {
+ this.HideTooltip();
+ }
+ }
+ }
+
+ this.OnKeyDown=function(e)
+ {
+ if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return;
+
+ var keyID = e.keyCode ? e.keyCode :e.which;
+ switch(keyID)
+ {
+ case 37: //left
+ if (this.CursorIndex<=0.99999)
+ {
+ if (!this.DataMoveLeft())
+ { //左移数据到头了 触发下载新数据
+ if (this.DragDownloadData) this.DragDownloadData();
+ break;
+ }
+ this.UpdataDataoffset();
+ this.UpdatePointByCursorIndex();
+ this.UpdateFrameMaxMin();
+ this.Draw();
+ this.ShowTooltipByKeyDown();
+ }
+ else
+ {
+ --this.CursorIndex;
+ this.UpdatePointByCursorIndex();
+ this.DrawDynamicInfo();
+ this.ShowTooltipByKeyDown();
+ }
+ break;
+ case 39: //right
+ var xPointcount=0;
+ if (this.Frame.XPointCount) xPointcount=this.Frame.XPointCount;
+ else xPointcount=this.Frame.SubFrame[0].Frame.XPointCount;
+ if (this.CursorIndex+1>=xPointcount)
+ {
+ if (!this.DataMoveRight()) break;
+ this.UpdataDataoffset();
+ this.UpdatePointByCursorIndex();
+ this.UpdateFrameMaxMin();
+ this.Draw();
+ this.ShowTooltipByKeyDown();
+ }
+ else
+ {
+ //判断是否在最后一个数据上
+ var data=null;
+ if (this.Frame.Data) data=this.Frame.Data;
+ else data=this.Frame.SubFrame[0].Frame.Data;
+ if (!data) break;
+ if (this.CursorIndex+data.DataOffset+1>=data.Data.length) break;
+
+ ++this.CursorIndex;
+ this.UpdatePointByCursorIndex();
+ this.DrawDynamicInfo();
+ this.ShowTooltipByKeyDown();
+ }
+ break;
+ case 38: //up
+ if (this.EnableZoomUpDown && this.EnableZoomUpDown.Keyboard===false) break;
+ var cursorIndex={ ZoomType:this.ZoomType };
+ cursorIndex.Index=parseInt(Math.abs(this.CursorIndex-0.5).toFixed(0));
+ if (!this.Frame.ZoomUp(cursorIndex)) break;
+ this.CursorIndex=cursorIndex.Index;
+ this.UpdatePointByCursorIndex();
+ this.UpdataDataoffset();
+ this.UpdateFrameMaxMin();
+ this.Draw();
+ this.ShowTooltipByKeyDown();
+ break;
+ case 40: //down
+ if (this.EnableZoomUpDown && this.EnableZoomUpDown.Keyboard===false) break;
+ var cursorIndex={ ZoomType:this.ZoomType };
+ cursorIndex.Index=parseInt(Math.abs(this.CursorIndex-0.5).toFixed(0));
+ if (!this.Frame.ZoomDown(cursorIndex)) break;
+ this.CursorIndex=cursorIndex.Index;
+ this.UpdataDataoffset();
+ this.UpdatePointByCursorIndex();
+ this.UpdateFrameMaxMin();
+ this.Draw();
+ this.ShowTooltipByKeyDown();
+ break;
+ case 46: //del
+ if (!this.SelectChartDrawPicture) break;
+ var drawPicture=this.SelectChartDrawPicture;
+ JSConsole.Chart.Log(drawPicture,"drawPicturedrawPicturedrawPicture")
+ this.SelectChartDrawPicture=null;
+ this.ClearChartDrawPicture(drawPicture); //删除选中的画图工具
+ break;
+ case 32: //space
+ this.OnMarkRectSelect(e);
+ break;
+ default:
+ return;
+ }
+
+ //不让滚动条滚动
+ if(e.preventDefault) e.preventDefault();
+ else e.returnValue = false;
+ }
+
+ this.OnDoubleClick=function(x,y,e)
+ {
+ //JSConsole.Chart.Log(e);
+ }
+
+ this.ZoomIndexWindow=function(frameID, option) //最大化/最小化指标窗口
+ {
+ if (frameID<0 || frameID>=this.Frame.SubFrame.length) return false;
+
+ return this.Frame.ZoomIndexWindow(frameID, option);
+ }
+
+ this.RemoveMinSizeWindows=function() //清空最小化窗口
+ {
+ if (!this.Frame.ZoomWindowsInfo) return;
+
+ var aryDeleteIndex=[], aryIndex=[]; //删除的索引, 保留的索引
+ for(var i=0;i10)
+ {
+ this.Canvas.beginPath();
+ if (this.Frame.IsHScreen===true)
+ {
+ this.Canvas.rect(border.Left,border.Top,border.Right-border.Left,border.TopEx-border.Top);
+ }
+ else
+ {
+ this.Canvas.rect(border.Left,border.Top,border.LeftEx-border.Left,border.Bottom-border.Top);
+ }
+
+ if (this.Canvas.isPointInPath(x,y)) return 2;
+ }
+
+ if (this.Frame.ChartBorder.RightExtendWidth>10)
+ {
+ this.Canvas.beginPath();
+ if (this.Frame.IsHScreen===true)
+ {
+ this.Canvas.rect(border.Left,border.BottomEx,border.Right-border.Left,border.Bottom-border.BottomEx);
+ }
+ else
+ {
+ this.Canvas.rect(border.RightEx,border.Top,border.Right-border.RightEx,border.Bottom-border.Top);
+ }
+
+ if (this.Canvas.isPointInPath(x,y)) return 3;
+ }
+
+ return -1;
+ }
+
+ this.OnMoveFromeBorder=function(index, yMove)
+ {
+ if (!this.Frame) return;
+
+ if (!this.Frame.OnMoveFromeBorder(index,yMove)) return ;
+
+ //this.Frame.SetSizeChage(true);
+ this.Frame.SetFrameBorderSizeChange();
+ this.Frame.ReDrawToolbar();
+ this.Draw();
+ }
+
+ this.OnZoomUpDownFrameY=function(obj, yMove)
+ {
+ if (!this.Frame) return;
+
+ if (!this.Frame.OnZoomUpDownFrameY(obj,yMove)) return ;
+
+ this.Frame.SetSizeChage(true);
+ this.Draw();
+ }
+
+ this.OnUpDonwFrameY=function(obj, yMove)
+ {
+ if (!this.Frame) return false;
+
+ if (!this.Frame.OnUpDonwFrameY(obj,yMove)) return false;
+
+ this.Frame.SetSizeChage(true);
+
+ return true;
+ }
+
+ this.CancelZoomUpDownFrameY=function(obj)
+ {
+ if (!this.Frame) return;
+
+ if (!this.Frame.CancelZoomUpDownFrameY(obj)) return ;
+
+ this.UpdateFrameMaxMin();
+ this.Frame.SetSizeChage(true);
+ this.Draw();
+ }
+
+ this.IsKLineContainer=function()
+ {
+ if (this.ClassName=='KLineChartContainer' || this.ClassName=='KLineChartHScreenContainer' ||
+ this.ClassName=="KLineTrainChartContainer" || this.ClassName=="CustomKLineChartContainer" ) return true;
+
+ return false;
+ }
+
+ this.UpdatePointByCursorIndex=function(type) //type 1=根据十字光标更新 2=强制取消十字光标
+ {
+ var pt={X:null, Y:null};
+ pt.X=this.Frame.GetXFromIndex(this.CursorIndex);
+ var index=Math.abs(this.CursorIndex-0.5);
+ if (this.IsKLineContainer()) index=this.CursorIndex;
+
+ var data=this.Frame.Data;
+ if (data.DataOffset+index0) textHeight=format.Height; //新版本高度有格式化类计算完成
+ var width=format.Width;
+
+ this.Tooltip.style.width = width+"px";
+ this.Tooltip.style.height =textHeight+"px";
+ //JSConsole.Chart.Log(`[JSChartContainer::ShowTooltip] left=${left} top=${top} xMove=${xMove}` );
+ //if (toolTip.ChartPaint.Name=="Overlay-KLine") this.Tooltip.style.height =220+"px";
+ this.Tooltip.style.position = "absolute";
+ //JSConsole.Chart.Log('[JSChartContainer::ShowTooltip] getBoundingClientRect() ',this.UIElement.getBoundingClientRect())
+ if (left+width>this.UIElement.getBoundingClientRect().width)
+ this.Tooltip.style.left = (left-width) + "px";
+ else
+ this.Tooltip.style.left = left + "px";
+
+ if (top+xMove+textHeight>this.UIElement.getBoundingClientRect().height-5)
+ this.Tooltip.style.top = (top-textHeight)+ "px";
+ else this.Tooltip.style.top = (top + xMove)+ "px";
+
+ this.Tooltip.className='jschart-tooltip';
+ this.Tooltip.innerHTML=format.Text;
+ this.Tooltip.style.display = "block";
+ }
+ else if (toolTip.Type===1) //信息地雷提示信息
+ {
+ var scrollPos=GetScrollPosition();
+ var left = x;
+ var top = y;
+
+ var format=g_DivTooltipDataForamt.Create('KLineInfoDataStringFormat');
+ format.Value=toolTip;
+ format.Symbol=this.Symbol;
+ format.LanguageID=this.LanguageID;
+ if (!format.Operator()) return;
+ var width=format.Width;
+
+ this.Tooltip.className='jchart-klineinfo-tooltip';
+ this.Tooltip.style.position = "absolute";
+ if(left+width>this.UIElement.getBoundingClientRect().width){
+ this.Tooltip.style.left = (left-width) + "px";
+ }else{
+ this.Tooltip.style.left = left + "px";
+ }
+
+ this.Tooltip.style.top = (top +xMove)+ "px";
+ this.Tooltip.style.width = width+"px";
+ this.Tooltip.style.height =null;
+ this.Tooltip.innerHTML=format.Text;
+ this.Tooltip.style.display = "block";
+ }
+ else if (toolTip.Type==2) //指标信息
+ {
+ var left = x;
+ var top = y;
+
+ var format=g_DivTooltipDataForamt.Create('KLineTradeDataStringFormat');
+ format.Value=toolTip;
+ format.Symbol=this.Symbol;
+ format.LanguageID=this.LanguageID;
+ if (!format.Operator()) return;
+ var width=format.Width;
+
+ this.Tooltip.className='jchart-klinetrade-tooltip';
+ this.Tooltip.style.position = "absolute";
+ this.Tooltip.style.left = left + "px";
+ this.Tooltip.style.top = (top +xMove)+ "px";
+ this.Tooltip.style.width = width+"px";
+ this.Tooltip.style.height =null;
+ this.Tooltip.innerHTML=format.Text;;
+ this.Tooltip.style.display = "block";
+ }
+ else if (toolTip.Type==3) //分时图异动信息
+ {
+ var left = x;
+ var top = y;
+
+ var format=g_DivTooltipDataForamt.Create('MinuteInfoDataStringFormat');
+ format.Value=toolTip;
+ format.Symbol=this.Symbol;
+ format.LanguageID=this.LanguageID;
+ if (!format.Operator()) return;
+ var width=format.Width;
+
+ this.Tooltip.className='jchart-minuteinfo-tooltip'; //分时图异动
+ this.Tooltip.style.position = "absolute";
+ this.Tooltip.style.left = left + "px";
+ this.Tooltip.style.top = (top +xMove)+ "px";
+ this.Tooltip.style.width = width+"px";
+ this.Tooltip.style.height =null;
+ this.Tooltip.innerHTML=format.Text;;
+ this.Tooltip.style.display = "block";
+ }
+ else if (toolTip.Type==4) //icon图标信息
+ {
+ var left = x;
+ var top = y;
+
+ var format=g_DivTooltipDataForamt.Create('IconDataStringFormat');
+ format.Value=toolTip;
+ format.Symbol=this.Symbol;
+ format.LanguageID=this.LanguageID;
+ if (!format.Operator()) return;
+ var width=format.Width;
+
+ this.Tooltip.className='jchart-iconinfo-tooltip'; //图标信息
+ this.Tooltip.style.position = "absolute";
+ this.Tooltip.style.left = left + "px";
+ this.Tooltip.style.top = (top +xMove)+ "px";
+ this.Tooltip.style.width = width+"px";
+ this.Tooltip.style.height =null;
+ this.Tooltip.innerHTML=format.Text;;
+ this.Tooltip.style.display = "block";
+ }
+ }
+
+ this.HideTooltip=function()
+ {
+ if (this.Tooltip.style.display!="none") this.Tooltip.style.display = "none";
+ }
+
+ this.ShowSelectRect=function(x,y,x2,y2)
+ {
+ var left = x;
+ var top = y;
+
+ var border=this.Frame.ChartBorder.GetBorder();
+
+ var borderRight=border.Right;
+ var borderLeft=border.Left;
+
+ if (x>borderRight) x=borderRight;
+ if (x2>borderRight) x2=borderRight;
+
+ if (xx2) left=x2;
+ if (y>y2) top=y2;
+
+ var width=Math.abs(x-x2);
+ var height=Math.abs(y-y2);
+
+ this.SelectRect.style.width = width+"px";
+ this.SelectRect.style.height =height+"px";
+ this.SelectRect.style.position = "absolute";
+ this.SelectRect.style.left = left +"px";
+ this.SelectRect.style.top = top +"px";
+ this.SelectRect.style.display = "block";
+ }
+
+ this.UpdateSelectRect=function(start,end)
+ {
+ if (!this.ChartPaint[0].Data) return;
+ var paint=this.GetRectSelectPaint();
+ if (!paint) return;
+
+ var data=this.ChartPaint[0].Data;
+ var startItem=data.Data[start];
+ var endItem=data.Data[end];
+
+ JSConsole.Chart.Log('[JSChartContainer::UpdateSelectRect]',startItem,endItem);
+ paint.SetPoint(startItem, { Index:0 });
+ paint.SetPoint(endItem, { Index:1 });
+
+ this.Draw();
+ }
+
+ this.HideSelectRect=function()
+ {
+ this.SelectRect.style.display = "none";
+ }
+
+ this.ResetFrameXYSplit=function()
+ {
+ if (typeof(this.Frame.ResetXYSplit)=='function')
+ this.Frame.ResetXYSplit();
+ }
+
+ this.UpdateFrameMaxMin=function()
+ {
+ var frameMaxMinData=new Array();
+
+ var chartPaint=new Array();
+
+ for(var i=0;irange.Min) frameItem.Range.Min=range.Min;
+ }
+ else
+ {
+ frameItem={ OverlayFrame:[] };
+ frameItem.Frame=paint.ChartFrame;
+ frameItem.Range=range;
+ frameMaxMinData.push(frameItem);
+ }
+ }
+
+ var mapFrame=new Map();
+ for(var i=0;irange.Min) frameItem.Range.Min=range.Min;
+ }
+ }
+ }
+
+ for(var i=0;i=data.Data.length) return false;
+
+ ++data.DataOffset;
+ return true;
+ }
+
+ this.UpdataDataoffset=function()
+ {
+ var data=null;
+ if (this.Frame.Data)
+ data=this.Frame.Data;
+ else
+ data=this.Frame.SubFrame[0].Frame.Data;
+
+ if (!data) return;
+
+ for(var i in this.ChartPaint)
+ {
+ var item =this.ChartPaint[i];
+ if (!item.Data) continue;
+ item.Data.DataOffset=data.DataOffset;
+ }
+
+ for(var i in this.OverlayChartPaint)
+ {
+ var item =this.OverlayChartPaint[i];
+ if (!item.Data) continue;
+ item.Data.DataOffset=data.DataOffset;
+ }
+
+ //叠加指标当前显示的数据偏移
+ for (var i in this.Frame.SubFrame)
+ {
+ var subFrame=this.Frame.SubFrame[i];
+ for(var j in subFrame.OverlayIndex)
+ {
+ var overlayItem=subFrame.OverlayIndex[j];
+ for(var k in overlayItem.ChartPaint)
+ {
+ var item=overlayItem.ChartPaint[k];
+ if (!item.Data) continue;
+ item.Data.DataOffset=data.DataOffset;
+ }
+ }
+ }
+
+ }
+
+ this.GetMoveOneStepWidth=function()
+ {
+ if (IFrameSplitOperator.IsPlusNumber(this.StepPixel)) return this.StepPixel;
+
+ var pixelRatio=GetDevicePixelRatio();
+ var mainFrame=this.Frame.SubFrame[0].Frame;
+ var dataWidth=mainFrame.DataWidth;
+ var distanceWidth=mainFrame.DistanceWidth;
+ var oneStepWidth=this.StepPixel;
+ var oneStepWidth=(dataWidth+distanceWidth)/pixelRatio;
+ if (oneStepWidth<1) oneStepWidth=1;
+
+ return oneStepWidth;
+ }
+
+ this.DataMove=function(step,isLeft)
+ {
+ var oneStepWidth=this.GetMoveOneStepWidth();
+ var moveStep=step;
+ step=parseInt(step/oneStepWidth); //除以4个像素
+ if (step<=0) return false;
+
+ var data=null;
+ if (!this.Frame.Data) data=this.Frame.Data;
+ else data=this.Frame.SubFrame[0].Frame.Data;
+ if (!data) return false;
+
+ var xPointcount=0;
+ if (this.Frame.XPointCount) xPointcount=this.Frame.XPointCount;
+ else xPointcount=this.Frame.SubFrame[0].Frame.XPointCount;
+ if (!xPointcount) return false;
+
+ if (this.Frame.SubFrame && this.Frame.SubFrame.length>0 && this.Frame.SubFrame[0].Frame)
+ {
+ var fristFrame=this.Frame.SubFrame[0].Frame;
+ if (fristFrame.DataWidth<=1 || fristFrame.DistanceWidth<=1) //K线在缩放很小的时候 移动加速
+ {
+ if (IFrameSplitOperator.IsPlusNumber(this.StepPixel))
+ step=moveStep*this.StepPixel;
+ }
+
+ }
+
+ if (isLeft) //-->
+ {
+ if (this.RightSpaceCount>0)
+ {
+ if (xPointcount+data.DataOffset>=data.Data.length+this.RightSpaceCount-1) return false;
+ data.DataOffset+=step;
+
+ if (data.DataOffset+xPointcount>=data.Data.length+this.RightSpaceCount)
+ data.DataOffset=data.Data.length-(xPointcount-this.RightSpaceCount);
+ }
+ else
+ {
+ if (xPointcount+data.DataOffset>=data.Data.length) return false;
+ data.DataOffset+=step;
+
+ if (data.DataOffset+xPointcount>=data.Data.length)
+ data.DataOffset=data.Data.length-xPointcount;
+ }
+ return true;
+ }
+ else //<--
+ {
+ if (data.DataOffset<=0) return false;
+
+ data.DataOffset-=step;
+ if (data.DataOffset<0) data.DataOffset=0;
+
+ return true;
+ }
+ }
+
+ //获取鼠标在当前子窗口id
+ this.GetSubFrameIndex=function(x,y)
+ {
+ if (!this.Frame.SubFrame || this.Frame.SubFrame.length<=0) return -1;
+
+ for(var i in this.Frame.SubFrame)
+ {
+ var frame=this.Frame.SubFrame[i].Frame;
+ var left=frame.ChartBorder.GetLeft();
+ var top=frame.ChartBorder.GetTop();
+ var height=frame.ChartBorder.GetHeight();
+ var width=frame.ChartBorder.GetWidth();
+
+ this.Canvas.beginPath();
+ this.Canvas.rect(left,top,width,height);
+ if (this.Canvas.isPointInPath(x,y)) return parseInt(i);
+
+ }
+ return 0;
+ }
+
+ //根据X坐标获取数据索引
+ this.GetDataIndexByPoint=function(x)
+ {
+ var frame=this.Frame;
+ if (this.Frame.SubFrame && this.Frame.SubFrame.length>0) frame=this.Frame.SubFrame[0].Frame;
+
+ var data=null;
+ if (this.Frame.Data)
+ data=this.Frame.Data;
+ else
+ data=this.Frame.SubFrame[0].Frame.Data;
+
+ if (!data || !frame) return;
+
+ var index=parseInt(frame.GetXData(x));
+
+ //JSConsole.Chart.Log('x='+ x +' date='+data.Data[data.DataOffset+index].Date);
+ return data.DataOffset+index;
+ }
+
+ //获取主数据
+ this.GetSelectRectData=function(selectData)
+ {
+ if (Math.abs(selectData.XStart-selectData.XEnd)<5) return false;
+
+ var startClientPos=this.PtInClient(selectData.XStart, selectData.YStart);
+ var endClientPos=this.PtInClient(selectData.XEnd, selectData.YEnd);
+
+ var data=null;
+ if (this.Frame.Data)
+ data=this.Frame.Data;
+ else
+ data=this.Frame.SubFrame[0].Frame.Data;
+
+ if (!data) return false;
+
+ var start=this.GetDataIndexByPoint(selectData.XStart);
+ var end=this.GetDataIndexByPoint(selectData.XEnd);
+
+ if (Math.abs(start-end)<2) return false;
+
+ selectData.Data=data;
+ if (start>end)
+ {
+ selectData.Start=end;
+ selectData.End=start;
+ }
+ else
+ {
+ selectData.Start=start;
+ selectData.End=end;
+ }
+
+ return true;
+ }
+
+ //获取当前的点对应的 画图工具的图形
+ //data.X data.Y 鼠标位置 返回 data.ChartDrawPicture 数据在画图工具 data.PointIndex 在画图工具对应点索引
+ this.GetChartDrawPictureByPoint=function(data)
+ {
+ for(var i in this.ChartDrawPicture)
+ {
+ var item =this.ChartDrawPicture[i];
+ var pointIndex=item.IsPointIn(data.X,data.Y);
+ if (pointIndex===false) continue;
+
+ if (pointIndex>=0)
+ {
+ data.ChartDrawPicture=item;
+ data.PointIndex=pointIndex;
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ // 保存图片
+ this.SaveToImage = function (format,colorGB)
+ {
+ if (this.UIElement.width<=0 || this.UIElement.height<=0) return null;
+ if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash) return null; // 数据加载中不能保存
+
+ JSConsole.Chart.Log('[JSChartContainer::SaveToImage]', this.UIElement);
+ var clrBG='rgb(255,255,255)';
+ if (colorGB) clrBG=colorGB;
+ this.Canvas.clearRect(0,0,this.UIElement.width,this.UIElement.height);
+ this.Canvas.fillStyle=clrBG;
+ this.Canvas.fillRect(0,0,this.UIElement.width,this.UIElement.height); //画一个背景色, 不然是一个黑的背景
+ var pixelTatio = GetDevicePixelRatio(); //获取设备的分辨率
+ this.Canvas.lineWidth=pixelTatio; //手机端需要根据分辨率比调整线段宽度
+
+ this.Frame.Draw(); //框架
+
+ for (var i in this.ChartPaint) //框架内图形
+ {
+ var item=this.ChartPaint[i];
+ if (item.IsDrawFirst)
+ item.Draw();
+ }
+
+ for(var i in this.ChartPaint)
+ {
+ var item=this.ChartPaint[i];
+ if (!item.IsDrawFirst)
+ item.Draw();
+ }
+
+ for(var i in this.ChartPaintEx)
+ {
+ var item=this.ChartPaintEx[i];
+ item.Draw();
+ }
+
+ for(var i in this.OverlayChartPaint) //叠加股票
+ {
+ var item=this.OverlayChartPaint[i];
+ item.Draw();
+ }
+
+
+ for(var i in this.ExtendChartPaint) //固定扩展图形
+ {
+ var item=this.ExtendChartPaint[i];
+ if (!item.IsDynamic && item.IsAnimation==false) item.Draw();
+ }
+
+ if (this.Frame.DrawInsideHorizontal) this.Frame.DrawInsideHorizontal();
+ this.Frame.DrawLock();
+
+ for(var i in this.ExtendChartPaint) //动态扩展图形
+ {
+ var item=this.ExtendChartPaint[i];
+ if (item.IsDynamic && item.DrawAfterTitle===false) item.Draw();
+ }
+
+ if (this.LastPoint.X!=null || this.LastPoint.Y!=null)
+ {
+ if (this.ChartCorssCursor) //十字光标不画
+ {
+ this.ChartCorssCursor.LastPoint=this.LastPoint;
+ this.ChartCorssCursor.CursorIndex=this.CursorIndex;
+ }
+ }
+
+ for(var i in this.TitlePaint)
+ {
+ var item=this.TitlePaint[i];
+ if (!item.IsDynamic) continue;
+
+ item.CursorIndex=this.CursorIndex;
+ item.Draw();
+ }
+
+ for(var i in this.ExtendChartPaint) //动态扩展图形
+ {
+ var item=this.ExtendChartPaint[i];
+ if (item.IsDynamic && item.DrawAfterTitle===true && item.IsAnimation==false) item.Draw();
+ }
+
+ if (this.EnableAnimation)
+ {
+ for(var i in this.ExtendChartPaint) //动画
+ {
+ var item=this.ExtendChartPaint[i];
+ if (item.IsAnimation===true) item.Draw();
+ }
+ }
+
+ for(var i in this.ChartDrawPicture)
+ {
+ var item=this.ChartDrawPicture[i];
+ item.Draw();
+ }
+
+ if (this.CurrentChartDrawPicture && this.CurrentChartDrawPicture.Status!=10)
+ {
+ this.CurrentChartDrawPicture.Draw();
+ }
+
+ var dataURL=this.UIElement.toDataURL(format ? format:'image/png', 1.0);
+ JSConsole.Chart.Log('[JSChartContainer::SaveToImage] data= ', dataURL);
+ return dataURL;
+ }
+
+
+ this.SaveToImageUrl=function(obj,callback) //obj:{Format: 图片格式, ColorGB: 背景色}, callback:function(bSuccess,obj)
+ {
+ if (!obj) obj={Format:'image/png', ColorGB:'rgb(255,255,255)'};
+ var imageData=this.SaveToImage(obj.Format, obj.ColorGB);
+ var postData={"Base64":imageData, "BucketName":"downloadcache", "Path":"hqchart/hq_snapshot"};
+ var url=g_JSChartResource.Domain+'/API/FileUploadForBase64';
+
+ JSNetwork.HttpRequest({
+ url: url,
+ method: "POST",
+ dataType: "json",
+ data: postData,
+ success: function (data)
+ {
+ JSConsole.Chart.Log('[JSChartContainer::SaveToImageUrl] recv data', data);
+ var result={Path:data.relativeurl, Domain:'https://opensourcedownload.zealink.com'};
+ result.Url=`${result.Domain}/${result.Path}`;
+ if (callback) callback(true,result,'');
+ },
+ error: function (request)
+ {
+ JSConsole.Chart.Log('[JSChartContainer::SaveToImageUrl] error ', request);
+ if (callback) callback(false,null,'upload failed');
+ }
+ });
+
+ }
+
+ this.SetLanguage=function(language)
+ {
+ var languageID=null;
+ switch(language)
+ {
+ case 'EN':
+ languageID=JSCHART_LANGUAGE_ID.LANGUAGE_ENGLISH_ID;
+ break;
+ case 'CN':
+ languageID=JSCHART_LANGUAGE_ID.LANGUAGE_CHINESE_ID;
+ break;
+ default:
+ console.warn(`[JSChartContainer::SetLanguage] language=${language} error`);
+ return;
+ }
+
+ if (this.LanguageID==languageID) return;
+
+ this.LanguageID=languageID;
+ if (this.ChartCorssCursor && this.ChartCorssCursor.StringFormatY) this.ChartCorssCursor.StringFormatY.LanguageID=this.LanguageID;
+
+ for(var i in this.TitlePaint)
+ {
+ var item=this.TitlePaint[i];
+ if (item) item.LanguageID=this.LanguageID;
+ }
+
+ if (this.Frame && this.Frame.SetLanguage) this.Frame.SetLanguage(this.LanguageID);
+
+ this.Frame.SetSizeChage(true);
+ this.Draw();
+ }
+
+ this.ReloadTiltePaintResource=function(resource) //重新加载配置
+ {
+ for(var i in this.TitlePaint)
+ {
+ var item=this.TitlePaint[i];
+ if (item.ReloadResource) item.ReloadResource(resource);
+ }
+ }
+
+ this.ReloadExtendChartPaintResource=function(resource) //扩展画法重新加载配置
+ {
+ for(var i in this.ExtendChartPaint)
+ {
+ var item=this.ExtendChartPaint[i];
+ if (item.ReloadResource) item.ReloadResource(resource);
+ }
+ }
+
+ this.ReloadResource=function(option)
+ {
+ this.ReloadBorder(option);
+ this.ReloadTiltePaintResource(option.Resource);
+ this.ReloadChartPaint(option.Resource);
+ this.ReloadFrame(option.Resource);
+ this.ReloadExtendChartPaintResource(option.Resource);
+ this.ReloadChartCorssCursor(option,option.Resource);
+
+ if (option.Update && this.Update) this.Update( {UpdateCursorIndexType:2} ); //是否立即更新并重绘
+ else if (option.Draw==true) this.Draw(); //是否立即重绘
+ }
+
+ this.ReloadBorder=function(option) //根据页面缩放调整对应边框的尺长
+ {
+ if (!option) return;
+
+ var pixelTatio = GetDevicePixelRatio(); //获取设备的分辨率
+ if (option.Border)
+ {
+ var item=option.Border;
+ if (IFrameSplitOperator.IsNumber(item.Left)) this.Frame.ChartBorder.Left=item.Left*pixelTatio;
+ if (IFrameSplitOperator.IsNumber(item.Right)) this.Frame.ChartBorder.Right=item.Right*pixelTatio;
+ if (IFrameSplitOperator.IsNumber(item.Top)) this.Frame.ChartBorder.Top=item.Top*pixelTatio;
+ if (IFrameSplitOperator.IsNumber(item.Bottom)) this.Frame.ChartBorder.Bottom=item.Bottom*pixelTatio;
+ }
+
+ for(var i in option.Windows)
+ {
+ var item=option.Windows[i];
+ if (i>=this.Frame.SubFrame.length) continue;
+ var subFrame=this.Frame.SubFrame[i];
+ var border=subFrame.Frame.ChartBorder;
+ if (IFrameSplitOperator.IsNumber(item.TitleHeight)) border.TitleHeight=item.TitleHeight*pixelTatio;
+ }
+
+ for(var i in option.Frame)
+ {
+ var item=option.Frame[i];
+ if (i>=this.Frame.SubFrame.length) continue;
+
+ var subFrame=this.Frame.SubFrame[i];
+ var border=subFrame.Frame.ChartBorder;
+ if (item.TopSpace>=0) border.TopSpace=item.TopSpace*pixelTatio;
+ if (item.BottomSpace>=0) border.BottomSpace=item.BottomSpace*pixelTatio;
+ }
+ }
+
+ this.ReloadFrame=function(resource)
+ {
+ for(var i in this.Frame.SubFrame)
+ {
+ var item=this.Frame.SubFrame[i];
+ var subFrame=item.Frame;
+ if (subFrame && subFrame.ReloadResource) subFrame.ReloadResource(resource);
+ }
+ }
+
+ this.ReloadChartPaint=function(resource)
+ {
+ for(var i in this.ChartPaint)
+ {
+ var item=this.ChartPaint[i];
+ if (item && item.ReloadResource) item.ReloadResource(resource);
+ }
+ }
+
+ this.ReloadChartCorssCursor=function(option, resource)
+ {
+ var pixelTatio = GetDevicePixelRatio(); //获取设备的分辨率
+ if (option && option.CorssCursor)
+ {
+ var item=option.CorssCursor;
+ if (IFrameSplitOperator.IsNumber(item.TitleHeight)) this.ChartCorssCursor.TextHeight=item.TitleHeight*pixelTatio; //十字光标文本信息高度
+ }
+
+ if (this.ChartCorssCursor.ReloadResource) this.ChartCorssCursor.ReloadResource(resource);
+ }
+
+ this.SetDepthMapData=function(depthData, bDraw)
+ {
+ for(var i in depthData)
+ {
+ var item=depthData[i];
+ for(var j in this.ExtendChartPaint)
+ {
+ var chart=this.ExtendChartPaint[j];
+ if (chart.ID==item.ID)
+ {
+ chart.Data=item.Data;
+ break;
+ }
+ }
+ }
+
+ if (bDraw) this.Draw();
+ }
+
+ //画图工具
+ //把X, Y绝对位置转成的相对位置的点
+ this.PointAbsoluteToRelative=function(x, y, isPhone)
+ {
+ var pt={ X:x, Y:y };
+ var pixelTatio = GetDevicePixelRatio(); //x,y是原始坐标 需要乘以放大倍速
+ var uiRect=this.UIElement.getBoundingClientRect(); //dom返回的是没有放大倍数的值
+
+ if (isPhone)
+ {
+ pt.X=x-uiRect.left*pixelTatio; //手机端 dom返回的是没有放大倍数的值
+ pt.Y=y-uiRect.top*pixelTatio;
+ }
+ else
+ {
+ pt.X=(x-uiRect.left)*pixelTatio;
+ pt.Y=(y-uiRect.top)*pixelTatio;
+ }
+
+ return pt;
+ }
+
+ this.SetChartDrawPictureFirstPoint=function(x,y, isPhone)
+ {
+ var drawPicture=this.CurrentChartDrawPicture;
+ if (!drawPicture) return false;
+ if (!this.Frame.SubFrame || this.Frame.SubFrame.length<=0) return false;
+
+ //相对坐标
+ var pt=this.PointAbsoluteToRelative(x, y, isPhone);
+ var xFixed=pt.X;
+ var yFixed=pt.Y;
+
+ for(var i in this.Frame.SubFrame)
+ {
+ var frame=this.Frame.SubFrame[i].Frame;
+ var left=frame.ChartBorder.GetLeft();
+ var top=frame.ChartBorder.GetTopEx();
+ var height=frame.ChartBorder.GetHeight();
+ var width=frame.ChartBorder.GetWidth();
+
+ this.Canvas.beginPath();
+ this.Canvas.rect(left,top,width,height);
+ if (this.Canvas.isPointInPath(xFixed,yFixed))
+ {
+ drawPicture.Frame=frame;
+ break;
+ }
+ }
+
+ if (!drawPicture.Frame) return false;
+
+ drawPicture.Point[0]=new Point();
+ drawPicture.Point[0].X=xFixed;
+ drawPicture.Point[0].Y=yFixed;
+ drawPicture.Status=1; //第1个点完成
+ return true;
+ }
+
+ this.SetChartDrawPictureSecondPoint=function(x,y,isPhone)
+ {
+ var drawPicture=this.CurrentChartDrawPicture;
+ if (!drawPicture) return false;
+
+ //相对坐标
+ var pt=this.PointAbsoluteToRelative(x, y, isPhone);
+
+ drawPicture.Point[1]=new Point();
+ drawPicture.Point[1].X=pt.X;
+ drawPicture.Point[1].Y=pt.Y;
+
+ drawPicture.Status=2; //设置第2个点
+ return true;
+ }
+
+ //设置第3个点
+ this.SetChartDrawPictureThirdPoint=function(x,y,isPhone)
+ {
+ var drawPicture=this.CurrentChartDrawPicture;
+ if (!drawPicture) return false;
+
+ //相对坐标
+ var pt=this.PointAbsoluteToRelative(x, y, isPhone);
+
+ drawPicture.Point[2]=new Point();
+ drawPicture.Point[2].X=pt.X;
+ drawPicture.Point[2].Y=pt.Y;
+
+ drawPicture.Status=3; //设置第3个点
+ return true;
+ }
+
+ //xStep,yStep 移动的偏移量
+ this.MoveChartDrawPicture=function(x,y,isPhone)
+ {
+ var drawPicture=this.CurrentChartDrawPicture;
+ if (!drawPicture) return false;
+
+ var pixelTatio = GetDevicePixelRatio(); //x,y 需要乘以放大倍速
+ if (isPhone) pixelTatio=1;
+ var xStep=x*pixelTatio;
+ var yStep=y*pixelTatio;
+ //JSConsole.Chart.Log("xStep="+xStep+" yStep="+yStep);
+ drawPicture.Move(xStep,yStep);
+
+ return true;
+ }
+
+ this.FinishChartDrawPicturePoint=function()
+ {
+ var drawPicture=this.CurrentChartDrawPicture;
+ if (!drawPicture) return false;
+ if (drawPicture.PointCount!=drawPicture.Point.length) return false;
+ if (drawPicture.ClassName=="ChartDrawRuler") //尺子不用保存的
+ {
+ this.CurrentChartDrawPicture=null;
+ return true;
+ }
+
+ drawPicture.Status=10; //完成
+ drawPicture.PointToValue();
+
+ this.ChartDrawPicture.push(drawPicture);
+ this.CurrentChartDrawPicture=null;
+
+ //通知上层画好了
+ let event=this.GetEventCallback(JSCHART_EVENT_ID.ON_FINISH_DRAWPICTURE); //完成画图工具事件
+ if (event && event.Callback)
+ {
+ let sendData={ DrawPicture: drawPicture };
+ event.Callback(event,sendData,this);
+ }
+ else if (drawPicture.FinishedCallback) drawPicture.FinishedCallback(drawPicture);
+
+ if (this.ChartDrawStorage) this.ChartDrawStorage.SaveDrawData(drawPicture);
+
+ return true;
+ }
+
+ //选中画图工具 出现单个图形设置菜单
+ this.OnSelectChartPicture=function(chart)
+ {
+ JSConsole.Chart.Log('[JSChartContainer::OnSelectChartPicture',chart);
+ if (!this.ChartPictureMenu) this.ChartPictureMenu=new ChartPictureSettingMenu(this.UIElement.parentNode);
+
+ var event={ data: { ChartPicture:chart, HQChart:this}};
+ this.ChartPictureMenu.DoModal(event);
+ }
+
+ this.FinishMoveChartDrawPicture=function()
+ {
+ var drawPicture=this.CurrentChartDrawPicture;
+ if (!drawPicture) return false;
+ if (drawPicture.PointCount!=drawPicture.Point.length) return false;
+
+ drawPicture.Status=10; //完成
+ drawPicture.PointToValue();
+
+ if (this.ChartDrawStorage) this.ChartDrawStorage.SaveDrawData(drawPicture);
+
+ this.CurrentChartDrawPicture=null;
+ return true;
+ }
+
+ //清空所有的画线工具
+ this.ClearChartDrawPicture=function(drawPicture)
+ {
+ if (!drawPicture)
+ {
+ this.ChartDrawPicture=[];
+ if (this.ChartDrawStorage) this.ChartDrawStorage.Clear();
+ this.Draw();
+ }
+ else
+ {
+ for(var i in this.ChartDrawPicture)
+ {
+ if (this.ChartDrawPicture[i]==drawPicture)
+ {
+ if (this.ChartDrawStorage) this.ChartDrawStorage.DeleteDrawData(drawPicture);
+ this.ChartDrawPicture.splice(i,1);
+ this.Draw();
+ }
+ }
+ }
+ }
+
+ this.SetChartDrawOption=function(option)
+ {
+ if (IFrameSplitOperator.IsBool(option.IsLockScreen)) this.ChartDrawOption.IsLockScreen=option.IsLockScreen;
+ if (IFrameSplitOperator.IsNumber(option.Zoom) && option.Zoom>=0) this.ChartDrawOption.Zoom=option.Zoom;
+ }
+
+ //是否显示十字光标的十字线
+ this.EnableShowCorssCursorLine=function(bShow)
+ {
+ if (!this.ChartCorssCursor) return;
+
+ this.ChartCorssCursor.IsShowCorss=bShow;
+ }
+
+ //获取扩展画法
+ this.GetExtendChartByClassName=function(name)
+ {
+ for(var i=0; i=this.ExtendChartPaint.length) return;
+ if (this.ExtendChartPaint[data.Index]!=data.Chart) return;
+
+ if (typeof(data.Chart.Clear)=='function') data.Chart.Clear();
+ this.ExtendChartPaint.splice(data.Index,1);
+ }
+
+ //全屏提示信息 { Title:提示信息, Draw:false/true 是否立即重绘, }
+ this.EnableSplashScreen=function(option)
+ {
+ if (!this.ChartSplashPaint) return;
+ if (!option) return;
+
+ if (IFrameSplitOperator.IsString(option.Title)) this.ChartSplashPaint.SetTitle(option.Title);
+ this.ChartSplashPaint.EnableSplash(true);
+
+ if (option.Draw===false) return;
+ this.Draw();
+ }
+
+ this.SetSubFrameOption=function(subFrame, option)
+ {
+ if (!option) return;
+
+ if (option.Window)
+ {
+ var item=option.Window;
+ if (item.Modify!=null) subFrame.Frame.ModifyIndex=item.Modify;
+ if (item.Change!=null) subFrame.Frame.ChangeIndex=item.Change;
+ if (item.Close!=null) subFrame.Frame.CloseIndex=item.Close;
+ if (item.Overlay!=null) subFrame.Frame.OverlayIndex=item.Overlay;
+ if (item.IsDrawTitleBG==true) subFrame.Frame.IsDrawTitleBG=item.IsDrawTitleBG;
+
+ if (item.OverlayIndexType)
+ {
+ if (IFrameSplitOperator.IsNumber(item.OverlayIndexType.Position)) subFrame.Frame.OverlayIndexType.Position=item.OverlayIndexType.Position;
+ if (IFrameSplitOperator.IsNumber(item.OverlayIndexType.LineSpace)) subFrame.Frame.OverlayIndexType.LineSpace=item.OverlayIndexType.LineSpace;
+ }
+ }
+
+ if (IFrameSplitOperator.IsNumber(option.SplitCount)) subFrame.Frame.YSplitOperator.SplitCount=option.SplitCount;
+ if (IFrameSplitOperator.IsNumber(option.TitleHeight)) subFrame.Frame.ChartBorder.TitleHeight=option.TitleHeight;
+ if (IFrameSplitOperator.IsBool(option.IsShowTitleArraw)) subFrame.Frame.IsShowTitleArraw=option.IsShowTitleArraw;
+ if (IFrameSplitOperator.IsBool(option.IsShowIndexName)) subFrame.Frame.IsShowIndexName=option.IsShowIndexName;
+ if (IFrameSplitOperator.IsBool(option.IsShowOverlayIndexName)) subFrame.Frame.IsShowOverlayIndexName=option.IsShowOverlayIndexName;
+ if (IFrameSplitOperator.IsNumber(option.IndexParamSpace)) subFrame.Frame.IndexParamSpace=option.IndexParamSpace;
+ if (IFrameSplitOperator.IsBool(option.IsShowXLine)) subFrame.Frame.IsShowXLine=option.IsShowXLine;
+ if (IFrameSplitOperator.IsBool(option.IsShowYLine)) subFrame.Frame.IsShowYLine=option.IsShowYLine;
+ if (IFrameSplitOperator.IsBool(option.IsShowIndexTitle)) subFrame.Frame.IsShowIndexTitle=option.IsShowIndexTitle;
+
+ if (IFrameSplitOperator.IsBool(option.IsShowLeftText))
+ {
+ subFrame.Frame.IsShowYText[0]=option.IsShowLeftText;
+ subFrame.Frame.YSplitOperator.IsShowLeftText=option.IsShowLeftText; //显示左边刻度
+ }
+ if (IFrameSplitOperator.IsBool(option.IsShowRightText))
+ {
+ subFrame.Frame.IsShowYText[1]=option.IsShowRightText;
+ subFrame.Frame.YSplitOperator.IsShowRightText=option.IsShowRightText; //显示右边刻度
+ }
+
+ }
+
+ //增加一个指标窗口
+ this.AddIndexWindow=function(indexName,option)
+ {
+ //查找系统指标
+ let scriptData = new JSIndexScript();
+ let indexInfo = scriptData.Get(indexName);
+ if (!indexInfo) return;
+
+ this.RemoveMinSizeWindows(); //清空隐藏的指标
+
+ var index=this.Frame.SubFrame.length;
+ var subFrame=this.CreateSubFrameItem(index);
+ var pixelRatio=GetDevicePixelRatio();
+ subFrame.Frame.ChartBorder.TitleHeight*=pixelRatio;
+ this.Frame.SubFrame[index]=subFrame;
+ var titlePaint=new DynamicChartTitlePainting();
+ titlePaint.Frame=this.Frame.SubFrame[index].Frame;
+ titlePaint.Canvas=this.Canvas;
+ titlePaint.LanguageID=this.LanguageID;
+ titlePaint.GetEventCallback=(id)=> { return this.GetEventCallback(id); }
+ this.TitlePaint[index+1]=titlePaint;
+
+ this.SetSubFrameOption(subFrame,option);
+
+ //最后一个显示X轴坐标
+ for(var i=0;i=0) indexData.FloatPrecision=option.FloatPrecision;
+ if (option.StringFormat>0) indexData.StringFormat=option.StringFormat;
+ if (option.Args) indexData.Args=option.Args;
+ }
+
+ this.WindowIndex[index] = new ScriptIndex(indexData.Name, indexData.Script, indexData.Args,indexData); //脚本执行
+ if (this.ClassName=="MinuteChartContainer" || this.ClassName=="MinuteChartHScreenContainer")
+ var bindData=this.SourceData;
+ else
+ var bindData=this.ChartPaint[0].Data;
+
+ this.BindIndexData(index,bindData); //执行脚本
+ }
+
+ //区间选择
+ this.GetRectSelectPaint=function()
+ {
+ for(var i=0;i=kData.Data.length) dataIndex=kData.Data.length-1;
+
+ var item = kData.Data[dataIndex];
+ JSConsole.Chart.Log("[KLineChartContainer::MoveRectSelectPoint] point, item", obj.PointIndex, item);
+
+ if (!paint.SetPoint(item,{ Index: obj.PointIndex })) return false;
+
+ var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_DRAG_SELECT_RECT);
+ if (event)
+ {
+ var selectData=paint.GetSelectRectData();
+ var data={ X:obj.X, Y:obj.Y, SelectData:selectData, RectSelectPaint:paint };
+ event.Callback(event,data,this);
+ }
+
+ return true;
+ }
+
+ this.ClearRectSelect=function(bEnforce)
+ {
+ var paint=this.GetRectSelectPaint();
+ if (!paint) return false;
+ if (bEnforce) paint.PreventClose=false;
+ return paint.ClearPoint();
+ }
+
+ //删除叠加指标, 没有重回
+ this.DeleteOverlayIndex=function(identify, windowIndex)
+ {
+ var findIndex=null;
+ if (IFrameSplitOperator.IsNumber(windowIndex))
+ {
+ if (windowIndex>=0 && windowIndex=this.Frame.SubFrame.length ) return false;
+ if ( !IFrameSplitOperator.IsNumber(dest.WindowIndex) || dest.WindowIndex<0 || dest.WindowIndex>=this.Frame.SubFrame.length ) return false;
+
+ var item=this.Frame.SubFrame[src.WindowIndex];
+ var findOverlayItem=null;
+ for(var i=0; i=this.Frame.SubFrame.length ) return false;
+
+ var item=this.Frame.SubFrame[src.WindowIndex];
+ var findOverlayItem=null;
+ for(var i=0; i { return this.GetEventCallback(id); }
+ this.TitlePaint[index+1]=titlePaint;
+
+ this.SetSubFrameOption(subFrame, option);
+
+ //最后一个显示X轴坐标
+ for(var i=0;i0) return true;
+ }
+ return false;
+}
+
+function OnKeyDown(e) //键盘事件
+{
+ if(this.JSChartContainer && this.JSChartContainer.OnKeyDown)
+ this.JSChartContainer.OnKeyDown(e);
+}
+
+function OnWheel(e) //上下滚动事件
+{
+ if(this.JSChartContainer && this.JSChartContainer.OnWheel)
+ this.JSChartContainer.OnWheel(e);
+}
+
+function ToFixed(number, precision)
+{
+ var b = 1;
+ if (isNaN(number)) return number;
+ if (number < 0) b = -1;
+ var multiplier = Math.pow(10, precision);
+ var value=Math.round(Math.abs(number) * multiplier) / multiplier * b;
+
+ if (/^(\d+(?:\.\d+)?)(e)([\-]?\d+)$/.test(value))
+ var s=value.toFixed2(precision);
+ else
+ var s = value.toString();
+
+ var rs = s.indexOf('.');
+ if (rs < 0 && precision>0)
+ {
+ rs = s.length;
+ s += '.';
+ }
+
+ while (s.length <= rs + precision)
+ {
+ s += '0';
+ }
+
+
+
+ return s;
+}
+
+Number.prototype.toFixed2=Number.prototype.toFixed; //备份下老的
+Number.prototype.toFixed = function( precision )
+{
+ return ToFixed(this,precision);
+}
+
+function Guid()
+{
+ function S4()
+ {
+ return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
+ }
+ return "guid" + (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4());
+}
+
+function GetScrollPosition()
+{
+ var scrollPos={};
+ var scrollTop=0;
+ var scrollLeft=0;
+ if(document.documentElement && document.documentElement.scrollTop)
+ {
+ scrollTop=document.documentElement.scrollTop;
+ scrollLeft=document.documentElement.scrollLeft;
+ }else if(document.body)
+ {
+ scrollTop=document.body.scrollTop;
+ scrollLeft=document.body.scrollLeft;
+ }
+
+ scrollPos.Top=scrollTop;
+ scrollPos.Left=scrollLeft;
+ return scrollPos;
+}
+
+//修正线段有毛刺
+function ToFixedPoint(value)
+{
+ return parseInt(value)+0.5;
+}
+
+//修正粗线段毛刺
+function ToFixedPoint2(width, value)
+{
+ var fixValue=(width % 2)===0 ? Math.floor(value):Math.floor(value) + 0.5; //毛边修正
+ return fixValue;
+}
+
+function ToFixedRect(value)
+{
+ // With a bitwise or.
+ //rounded = (0.5 + somenum) | 0;
+ // A double bitwise not.
+ //rounded = ~~ (0.5 + somenum);
+ // Finally, a left bitwise shift.
+ //value*=GetDevicePixelRatio();
+ var rounded;
+ return rounded = (0.5 + value) << 0;
+}
+
+
+
+function Point()
+{
+ this.X;
+ this.Y;
+}
+
+function SelectRectData()
+{
+ this.Data; //主数据
+ this.JSChartContainer; //行情控件
+
+ this.Start; //数据起始位子
+ this.End; //数据结束位置
+
+ this.XStart;//X坐标起始位置
+ this.YStart;
+ this.XEnd; //X位置结束为止
+ this.YEnd;
+}
+
+//坐标信息
+function CoordinateInfo()
+{
+ this.Value; //坐标数据
+ this.Message=[]; //坐标输出文字信息 0=左 1=右 2=内左 3=内右
+ this.TextColor=g_JSChartResource.FrameSplitTextColor //文字颜色
+ this.Font=g_JSChartResource.FrameSplitTextFont; //字体
+ this.LineColor=g_JSChartResource.FrameSplitPen; //线段颜色
+ this.LineType=1; //线段类型 -1 不画线段 2 虚线 8,9=集合竞价坐标
+ this.ExtendData; //扩展属性
+ //百分比 { PriceColor:, PercentageColor:, SplitColor:, Font: }
+}
+
+
+//边框信息
+function ChartBorder()
+{
+ this.UIElement;
+
+ //四周间距
+ this.Left=50;
+ this.Right=80;
+ this.Top=50;
+ this.Bottom=50;
+ this.TitleHeight=24; //标题高度
+ this.TopSpace=0;
+ this.BottomSpace=0;
+
+ this.LeftExtendWidth=0; //左边扩展图形宽度
+ this.RightExtendWidth=0;
+
+ this.MultiDayMinute={ Count:1, Left:0, Right:0 } // { Count:天数, Left:, Right: }
+
+ this.GetBorder=function()
+ {
+ var data=
+ {
+ Left:this.Left,
+ LeftEx:this.Left+this.LeftExtendWidth,
+ Right:this.UIElement.width-this.Right,
+ RightEx:this.UIElement.width-this.Right-this.RightExtendWidth,
+
+ Top:this.Top,
+ TopEx:this.Top+this.TitleHeight+this.TopSpace,
+ TopTitle:this.Top+this.TitleHeight,
+ Bottom:this.UIElement.height-this.Bottom,
+ BottomEx:this.UIElement.height-this.Bottom-this.BottomSpace,
+
+ ChartWidth:this.UIElement.width,
+ ChartHeight:this.UIElement.height
+ };
+
+ if (this.MultiDayMinute && this.MultiDayMinute.Count>1 && ( this.MultiDayMinute.Left>0 || this.MultiDayMinute.Right>0 ))
+ {
+ var frameWidth=this.UIElement.width-this.Left-this.Right; //坐标框子宽度
+ var dayWidth=frameWidth/this.MultiDayMinute.Count; // 每天的框子的宽度
+
+ var dayBorder=[];
+ for(var i=0;i10)
+ {
+ canvas.beginPath();
+ if (isHScreen===true)
+ {
+ canvas.rect(border.Left,border.Top,border.Right-border.Left,border.TopEx-border.Top);
+ }
+ else
+ {
+ canvas.rect(border.Left,border.Top,border.LeftEx-border.Left,border.Bottom-border.Top);
+ }
+
+ if (canvas.isPointInPath(x,y)) return 2;
+ }
+
+ if (this.RightExtendWidth>10)
+ {
+ canvas.beginPath();
+ if (isHScreen===true)
+ {
+ canvas.rect(border.Left,border.BottomEx,border.Right-border.Left,border.Bottom-border.BottomEx);
+ }
+ else
+ {
+ canvas.rect(border.RightEx,border.Top,border.Right-border.RightEx,border.Bottom-border.Top);
+ }
+
+ if (canvas.isPointInPath(x,y)) return 3;
+ }
+
+ return -1;
+ }
+
+ this.GetChartWidth=function()
+ {
+ return this.UIElement.width;
+ }
+
+ this.GetChartHeight=function()
+ {
+ return this.UIElement.height;
+ }
+
+ this.GetLeft=function()
+ {
+ return this.Left+this.LeftExtendWidth;
+ }
+
+ this.GetRight=function()
+ {
+ return this.UIElement.width-this.Right-this.RightExtendWidth;
+ }
+
+ this.GetTop=function()
+ {
+ return this.Top;
+ }
+
+ this.GetTopEx=function() //去掉标题,上面间距
+ {
+ return this.Top+this.TitleHeight+this.TopSpace;
+ }
+
+ this.GetTopTitle=function() //去掉标题
+ {
+ return this.Top+this.TitleHeight;
+ }
+
+ this.GetBottom=function()
+ {
+ return this.UIElement.height-this.Bottom;
+ }
+
+ this.GetBottomEx=function()
+ {
+ return this.UIElement.height-this.Bottom-this.BottomSpace;
+ }
+
+ this.GetWidth=function()
+ {
+ return this.UIElement.width-this.Left-this.Right-this.LeftExtendWidth-this.RightExtendWidth;
+ }
+
+ this.GetHeight=function()
+ {
+ return this.UIElement.height-this.Top-this.Bottom;
+ }
+
+ this.GetHeightEx=function() //去掉标题的高度, 上下间距
+ {
+ return this.UIElement.height-this.Top-this.Bottom-this.TitleHeight-this.TopSpace-this.BottomSpace;
+ }
+
+ this.GetRightEx=function() //横屏去掉标题高度的 上面间距
+ {
+ return this.UIElement.width-this.Right-this.TitleHeight- this.TopSpace;
+ }
+
+ this.GetWidthEx=function() //横屏去掉标题宽度 上下间距
+ {
+ return this.UIElement.width-this.Left-this.Right-this.TitleHeight- this.TopSpace - this.BottomSpace;
+ }
+
+ this.GetLeftEx = function () //横屏
+ {
+ return this.Left+this.BottomSpace;
+ }
+
+ this.GetRightTitle = function ()//横屏
+ {
+ return this.UIElement.width - this.Right - this.TitleHeight;
+ }
+
+ this.GetTitleHeight=function()
+ {
+ return this.TitleHeight;
+ }
+}
+
+function IChartFramePainting()
+{
+ this.HorizontalInfo=new Array(); //Y轴
+ this.VerticalInfo=new Array(); //X轴
+ this.ClassName='IChartFramePainting';
+
+ this.Canvas; //画布
+
+ this.Identify; //窗口标识
+
+ this.ChartBorder;
+ this.PenBorder=g_JSChartResource.FrameBorderPen; //边框颜色
+ this.TitleBGColor=g_JSChartResource.FrameTitleBGColor; //标题背景色
+ this.IsShow=true; //是否显示
+ this.SizeChange=true; //大小是否改变
+ this.XYSplit=true; //XY轴坐标信息改变
+
+ this.HorizontalMax; //Y轴最大值
+ this.HorizontalMin; //Y轴最小值
+ this.XPointCount=10; //X轴数据个数
+
+ this.YSplitOperator; //Y轴分割
+ this.XSplitOperator; //X轴分割
+ this.Data; //主数据
+
+ this.IsLocked=false; //是否上锁
+ this.LockPaint = null;
+
+ this.YSpecificMaxMin=null; //指定Y轴最大最小值
+ this.IsShowBorder = true; //是否显示边框
+ this.IsShowTitleArraw=true; //是否显示指标信息上涨下跌箭头
+ this.IsShowIndexName=true; //是否显示指标名字
+ this.IsShowOverlayIndexName=true; //是否显示叠加指标名字
+ this.OverlayIndexType= { Position:0, LineSpace:5 };
+ this.IndexParamSpace=2; //指标参数数值显示间距
+ this.IsShowIndexTitle=true; //显示整个指标标题信息
+ this.IsDrawTitleBottomLine=false;
+
+ this.BorderLine=null; //1=上 2=下 4=左 8=右
+ this.Buttons=[]; //按钮事件
+
+ this.IsMinSize=false; //窗口是否最小化
+
+
+ this.PtInButtons=function(x,y) //坐标是否在按钮上
+ {
+ for(var i=0;i0) //上
+ {
+ this.Canvas.moveTo(left,top);
+ this.Canvas.lineTo(right,top);
+ }
+
+ if ((this.BorderLine&2)>0) //下
+ {
+ this.Canvas.moveTo(left,bottom);
+ this.Canvas.lineTo(right,bottom);
+ }
+
+ if ((this.BorderLine&4)>0) //左
+ {
+ this.Canvas.moveTo(left,top);
+ this.Canvas.lineTo(left,bottom);
+ }
+
+ if ((this.BorderLine&8)>0) //右
+ {
+ this.Canvas.moveTo(right,top);
+ this.Canvas.lineTo(right,bottom);
+ }
+
+ this.Canvas.stroke();
+ }
+
+
+ }
+
+ //画标题背景色
+ this.DrawTitleBG=function()
+ {
+ if (this.ChartBorder.TitleHeight<=0) return;
+
+ var border=this.GetBorder();
+
+ var left=ToFixedPoint(border.Left);
+ var top=ToFixedPoint(border.Top);
+ var right=ToFixedPoint(border.Right);
+ var bottom=ToFixedPoint(this.ChartBorder.GetTopTitle());
+ var width=right-left;
+ var height=bottom-top;
+
+ this.Canvas.fillStyle=this.TitleBGColor;
+ this.Canvas.fillRect(left,top,width,height);
+
+ if (this.IsDrawTitleBottomLine)
+ {
+ this.Canvas.strokeStyle=this.PenBorder;
+ this.Canvas.beginPath();
+ this.Canvas.moveTo(left,ToFixedPoint(border.TopTitle));
+ this.Canvas.lineTo(right,ToFixedPoint(border.TopTitle));
+ this.Canvas.stroke();
+ }
+ }
+
+ this.DrawLock=function()
+ {
+ if (this.IsLocked)
+ {
+ if (this.LockPaint == null)
+ this.LockPaint = new ChartLock();
+ this.LockPaint.Canvas=this.Canvas;
+ this.LockPaint.ChartBorder=this.ChartBorder;
+ this.LockPaint.ChartFrame=this;
+ this.LockPaint.Draw(true);
+ }
+ }
+
+ this.CalculateLock=function()
+ {
+ if (this.IsLocked)
+ {
+ if (this.LockPaint == null)
+ this.LockPaint = new ChartLock();
+ this.LockPaint.Canvas=this.Canvas;
+ this.LockPaint.ChartBorder=this.ChartBorder;
+ this.LockPaint.ChartFrame=this;
+ this.LockPaint.Draw(false);
+ }
+ }
+
+ //设施上锁
+ this.SetLock=function(lockData)
+ {
+ if (!lockData) //空数据不上锁
+ {
+ this.IsLocked=false;
+ return;
+ }
+
+ this.IsLocked=true;
+ if (!this.LockPaint) this.LockPaint=new ChartLock(); //创建锁
+
+ if (lockData.Callback) this.LockPaint.Callback=lockData.Callback; //回调
+ if (lockData.IndexName) this.LockPaint.IndexName=lockData.IndexName; //指标名字
+ if (lockData.ID) this.LockPaint.LockID=lockData.ID; //锁ID
+ if (lockData.BG) this.LockPaint.BGColor=lockData.BG; //背景色
+ if (lockData.Text) this.LockPaint.Title= lockData.Text;
+ if (lockData.TextColor) this.LockPaint.TextColor=lockData.TextColor;
+ if (lockData.Font) this.LockPaint.Font=lockData.Font;
+ if (lockData.Count) this.LockPaint.LockCount=lockData.Count;
+ if (lockData.MinWidth>0) this.LockPaint.MinWidth=lockData.MinWidth;
+ }
+
+ this.GetLockRect=function()
+ {
+ if (!this.IsLocked) return null;
+ if (!this.LockPaint) return null;
+ return this.LockPaint.LockRect;
+ }
+
+ this.ReloadResource=function(resource)
+ {
+ if (!resource)
+ {
+ this.PenBorder=g_JSChartResource.FrameBorderPen; //边框颜色
+ this.TitleBGColor=g_JSChartResource.FrameTitleBGColor; //标题背景色
+ }
+
+ for(var i in this.HorizontalInfo)
+ {
+ var item=this.HorizontalInfo[i];
+ if (item.Font) item.Font=g_JSChartResource.FrameSplitTextFont; //字体
+ if (item.TextColor) item.TextColor=g_JSChartResource.FrameSplitTextColor //文字颜色
+ if (item.LineColor) item.LineColor=g_JSChartResource.FrameSplitPen; //线段颜色
+ }
+
+ for(var i in this.VerticalInfo)
+ {
+ var item=this.VerticalInfo[i];
+ if (item.Font) item.Font=g_JSChartResource.FrameSplitTextFont; //字体
+ if (item.TextColor) item.TextColor=g_JSChartResource.FrameSplitTextColor //文字颜色
+ if (item.LineColor) item.LineColor=g_JSChartResource.FrameSplitPen; //线段颜色
+ }
+ }
+
+ this.GetFontHeight=function(font)
+ {
+ return GetFontHeight(this.Canvas, font, "擎");
+ }
+
+ //左右刻度文字宽度
+ this.GetScaleTextWidth=function()
+ {
+
+ }
+}
+
+//空框架只画边框
+function NoneFrame()
+{
+ this.newMethod=IChartFramePainting; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.ClassName="NoneFrame";
+
+ this.Snapshot=function()
+ {
+
+ }
+
+ this.SetSizeChage=function(sizeChange)
+ {
+ this.SizeChange=sizeChange;
+
+ //画布的位置
+ this.Position={
+ X:this.ChartBorder.UIElement.offsetLeft,
+ Y:this.ChartBorder.UIElement.offsetTop,
+ W:this.ChartBorder.UIElement.clientWidth,
+ H:this.ChartBorder.UIElement.clientHeight
+ };
+ }
+}
+
+function AverageWidthFrame()
+{
+ this.newMethod=IChartFramePainting; //派生
+ this.newMethod();
+ delete this.newMethod;
+
+ this.ClassName="AverageWidthFrame";
+ this.DataWidth=50*GetDevicePixelRatio();
+ this.DistanceWidth=10*GetDevicePixelRatio();
+ this.MinXDistance = 30*GetDevicePixelRatio(); //X轴刻度最小间距
+ this.MinYDistance=12*GetDevicePixelRatio(); //Y轴刻度最小间距
+ this.CoordinateType=0; //坐标类型 0=普通坐标 1=反转坐标
+ this.IsShowYText=[true,true]; //是否显示Y轴坐标坐标 [0=左侧] [1=右侧]
+ this.XBottomOffset=g_JSChartResource.Frame.XBottomOffset; //X轴文字显示向下偏移
+ this.YTextTopOffset=g_JSChartResource.Frame.YTopOffset; //Y轴顶部文字向下偏移
+ this.YTextPosition=[0,0], //是坐标否强制画在内部 [0=左侧] [1=右侧] 1=OUT" , 2=INSIDE
+ this.IsShowXLine=true; //是否显示X轴刻度线
+ this.IsShowYLine=true;
+ this.YInsideOffset=0;
+ this.YTextBaseline=0; //0=居中 1=上部 (目前就支持内部刻度)
+ this.MultiTextFormat=0; //多行刻度信息显示模式 0=显示第1行 1=价格/百分比 2=显示2行
+ this.RightTextMaxWidth=0;
+
+ this.ShortYLineLength=5;
+ this.ShortXLineLength=5;
+ this.DrawDepthMapCallback; //绘制深度图
+
+ this.DrawFrame=function()
+ {
+ if (this.XPointCount>0)
+ {
+ let dInterval=this.ChartBorder.GetWidth()/(6*this.XPointCount); //分6份, 数据4 间距2
+ this.DistanceWidth=2*dInterval;
+ this.DataWidth=4*dInterval;
+ }
+
+ this.DrawHorizontal();
+ this.DrawVertical();
+ }
+
+ //isLimit 是否限制在当前坐标下
+ this.GetYFromData=function(value, isLimit)
+ {
+ if (this.Logarithmic && this.GetYLogarithmicFromData)
+ {
+ return this.GetYLogarithmicFromData(value, isLimit);
+ }
+
+ if (isLimit===false)
+ {
+ if (this.CoordinateType==1)
+ {
+ var height=this.ChartBorder.GetHeightEx()*(value-this.HorizontalMin)/(this.HorizontalMax-this.HorizontalMin);
+ return this.ChartBorder.GetTopEx()+height;
+ }
+ else
+ {
+ var height=this.ChartBorder.GetHeightEx()*(value-this.HorizontalMin)/(this.HorizontalMax-this.HorizontalMin);
+ return this.ChartBorder.GetBottomEx()-height;
+ }
+ }
+ else
+ {
+ if (this.CoordinateType==1)
+ {
+ if(value<=this.HorizontalMin) return this.ChartBorder.GetTopEx();
+ if(value>=this.HorizontalMax) return this.ChartBorder.GetBottomEx();
+
+ var height=this.ChartBorder.GetHeightEx()*(value-this.HorizontalMin)/(this.HorizontalMax-this.HorizontalMin);
+ return this.ChartBorder.GetTopEx()+height;
+ }
+ else
+ {
+ if(value<=this.HorizontalMin) return this.ChartBorder.GetBottomEx();
+ if(value>=this.HorizontalMax) return this.ChartBorder.GetTopEx();
+
+ var height=this.ChartBorder.GetHeightEx()*(value-this.HorizontalMin)/(this.HorizontalMax-this.HorizontalMin);
+ return this.ChartBorder.GetBottomEx()-height;
+ }
+ }
+ }
+
+ //画Y轴
+ this.DrawHorizontal=function()
+ {
+ this.RightTextMaxWidth=0;
+ if (!IFrameSplitOperator.IsNonEmptyArray(this.HorizontalInfo)) return;
+
+ var border=this.ChartBorder.GetBorder();
+ var left=border.Left;
+ var right=border.Right
+ var bottom = border.Bottom
+ var top = this.ChartBorder.GetTopTitle();
+ var borderRight=this.ChartBorder.Right;
+ var borderLeft=this.ChartBorder.Left;
+
+ var isDrawLeft=borderLeft>10 && this.IsShowYText[0]===true && this.YTextPosition[0]!=2;
+ var isDrawRight=borderRight>10 && this.IsShowYText[1]===true && this.YTextPosition[1]!=2;
+
+ var yPrev=null; //上一个坐标y的值
+ var pixelRatio=GetDevicePixelRatio();
+ var itemHeight=(border.BottomEx-border.TopEx)/this.HorizontalInfo.length;
+ var aryMultiText=[];
+ for(var i=this.HorizontalInfo.length-1; i>=0; --i) //从上往下画分割线
+ {
+ var item=this.HorizontalInfo[i];
+ var y=this.GetYFromData(item.Value);
+ if (y!=null && yPrev!=null && Math.abs(y-yPrev)0)
+ {
+ if (g_JSChartResource.FrameYLineDash)
+ {
+ this.Canvas.setLineDash(g_JSChartResource.FrameYLineDash); //虚线
+ this.Canvas.beginPath();
+ this.Canvas.moveTo(left,yFixed);
+ this.Canvas.lineTo(right,yFixed);
+ this.Canvas.stroke();
+ this.Canvas.setLineDash([]);
+ }
+ else
+ {
+ this.Canvas.beginPath();
+ this.Canvas.moveTo(left,yFixed);
+ this.Canvas.lineTo(right,yFixed);
+ this.Canvas.stroke();
+ }
+ }
+ }
+
+ var yText=y;
+ if (y >= bottom - 2)
+ {
+ this.Canvas.textBaseline = 'bottom';
+ }
+ else if (y <= top + 2)
+ {
+ this.Canvas.textBaseline = 'top';
+ yText+=this.YTextTopOffset;
+ }
+ else
+ {
+ this.Canvas.textBaseline = "middle";
+ }
+
+ //坐标信息 左边 间距小于10 不画坐标
+ this.Canvas.strokeStyle=item.TextColor;
+ this.Canvas.fillStyle=item.TextColor;
+
+ if (item.Message[0]!=null && isDrawLeft)
+ {
+ if (item.Font!=null) this.Canvas.font=item.Font;
+
+ this.Canvas.textAlign="right";
+ this.Canvas.fillText(item.Message[0],left-2,yText);
+ }
+
+ //坐标信息 右边 间距小于10 不画坐标
+ if (item.Message[1]!=null && isDrawRight)
+ {
+ if (item.Font!=null) this.Canvas.font=item.Font;
+
+ var xText=right;
+ if (item.LineType==3)
+ {
+ var lineLength=this.ShortYLineLength*GetDevicePixelRatio();
+ this.Canvas.beginPath();
+ this.Canvas.moveTo(xText,yFixed);
+ this.Canvas.lineTo(xText+lineLength,yFixed);
+ this.Canvas.stroke();
+
+ xText+=lineLength;
+ }
+
+ this.Canvas.textAlign="left";
+ if (Array.isArray(item.Message[1]))
+ {
+ if (this.MultiTextFormat==1) //显示1行 格式:价格/百分比
+ {
+ if (item.ExtendData)
+ {
+ if (item.ExtendData.Font) this.Canvas.font=item.ExtendData.Font;
+ }
+
+ var textData=
+ {
+ Text:
+ [
+ {Text:item.Message[1][0], Width:this.Canvas.measureText(item.Message[1][0]).width },
+ {Text:item.Message[1][1], Width:this.Canvas.measureText(item.Message[1][1]).width }
+ ],
+ X:xText+2,
+ Y:yText,
+ TextBaseline:this.Canvas.textBaseline,
+ Item:item
+ }
+ aryMultiText.push(textData);
+ }
+ else if (this.MultiTextFormat==2) //显示2行
+ {
+ this.Canvas.fillText(item.Message[1][0],xText+2,yText);
+ var lineHeight=this.Canvas.measureText('M').width;
+ if (itemHeight>lineHeight*2) this.Canvas.fillText(item.Message[1][1],xText+2,yText+lineHeight);
+ }
+ else //显示第1行
+ {
+ this.Canvas.fillText(item.Message[1][0],xText+2,yText);
+ }
+ }
+ else
+ {
+ this.Canvas.fillText(item.Message[1],xText+2,yText);
+ }
+
+ }
+
+ yPrev=y;
+ }
+
+ if (IFrameSplitOperator.IsNonEmptyArray(aryMultiText) && this.MultiTextFormat==1) this.DrawHorizontalMuText(aryMultiText)
+ }
+
+ this.DrawHorizontalMuText=function(aryText)
+ {
+ var maxWidth=[null,null];
+ for(var i=0;i]