From 4548cb348622f7868734082a1faebddd6d0a6575 Mon Sep 17 00:00:00 2001 From: lizhixin <382352532@qq.com> Date: Thu, 27 May 2021 01:16:02 +0800 Subject: [PATCH] =?UTF-8?q?=E7=9F=AD=E6=9C=9F=E8=83=9C=E7=8E=87=E8=A1=A5?= =?UTF-8?q?=E5=85=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 118 ++++ package.json | 1 + src/App.vue | 34 +- src/layout/dashboard/DashboardLayout.vue | 5 + src/pages/ReCheck/AccountInfo.vue | 74 +++ src/pages/ReCheck/OrderTable.vue | 75 +++ src/pages/ReCheck/index.vue | 651 +++++++++++++++++++++++ src/pages/WinRate/index.vue | 201 +++++-- src/router/routes.js | 7 +- vue.config.js | 41 +- 10 files changed, 1130 insertions(+), 77 deletions(-) create mode 100644 src/pages/ReCheck/AccountInfo.vue create mode 100644 src/pages/ReCheck/OrderTable.vue create mode 100644 src/pages/ReCheck/index.vue diff --git a/package-lock.json b/package-lock.json index 4a01a89..95f99fd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11375,6 +11375,124 @@ } } }, + "uglifyjs-webpack-plugin": { + "version": "2.2.0", + "resolved": "https://registry.npm.taobao.org/uglifyjs-webpack-plugin/download/uglifyjs-webpack-plugin-2.2.0.tgz", + "integrity": "sha1-51vIDn8ZN/cllUybTFoeln6p0Nc=", + "dev": true, + "requires": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^1.7.0", + "source-map": "^0.6.1", + "uglify-js": "^3.6.0", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + }, + "dependencies": { + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/find-cache-dir/download/find-cache-dir-2.1.0.tgz", + "integrity": "sha1-jQ+UzRP+Q8bHwmGg2GEVypGMBfc=", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/find-up/download/find-up-3.0.0.tgz?cache=0&sync_timestamp=1597169842138&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffind-up%2Fdownload%2Ffind-up-3.0.0.tgz", + "integrity": "sha1-SRafHXmTQwZG2mHsxa41XCHJe3M=", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/locate-path/download/locate-path-3.0.0.tgz", + "integrity": "sha1-2+w7OrdZdYBxtY/ln8QYca8hQA4=", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npm.taobao.org/make-dir/download/make-dir-2.1.0.tgz?cache=0&sync_timestamp=1587567572251&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmake-dir%2Fdownload%2Fmake-dir-2.1.0.tgz", + "integrity": "sha1-XwMQ4YuL6JjMBwCSlaMK5B6R5vU=", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/p-locate/download/p-locate-3.0.0.tgz", + "integrity": "sha1-Mi1poFwCZLJZl9n0DNiokasAZKQ=", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/path-exists/download/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/pkg-dir/download/pkg-dir-3.0.0.tgz?cache=0&sync_timestamp=1602859045787&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpkg-dir%2Fdownload%2Fpkg-dir-3.0.0.tgz", + "integrity": "sha1-J0kCDyOe2ZCIGx9xIQ1R62UjvqM=", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npm.taobao.org/schema-utils/download/schema-utils-1.0.0.tgz", + "integrity": "sha1-C3mpMgTXtgDUsoUNH2bCo0lRx3A=", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.nlark.com/semver/download/semver-5.7.1.tgz?cache=0&sync_timestamp=1618847119601&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fsemver%2Fdownload%2Fsemver-5.7.1.tgz", + "integrity": "sha1-qVT5Ma66UI0we78Gnv8MAclhFvc=", + "dev": true + }, + "serialize-javascript": { + "version": "1.9.1", + "resolved": "https://registry.npm.taobao.org/serialize-javascript/download/serialize-javascript-1.9.1.tgz?cache=0&sync_timestamp=1599740650381&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fserialize-javascript%2Fdownload%2Fserialize-javascript-1.9.1.tgz", + "integrity": "sha1-z8IArvd7YAxH2pu4FJyUPnmML9s=", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz?cache=0&sync_timestamp=1571657176668&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsource-map%2Fdownload%2Fsource-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "dev": true + }, + "uglify-js": { + "version": "3.13.7", + "resolved": "https://registry.nlark.com/uglify-js/download/uglify-js-3.13.7.tgz?cache=0&sync_timestamp=1621369323186&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fuglify-js%2Fdownload%2Fuglify-js-3.13.7.tgz", + "integrity": "sha1-JUaKOzmxyHXfA/CTeytwNqk/P+4=", + "dev": true + } + } + }, "unbox-primitive": { "version": "1.0.1", "resolved": "https://registry.nlark.com/unbox-primitive/download/unbox-primitive-1.0.1.tgz", diff --git a/package.json b/package.json index 20e22de..b898402 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "@vue/cli-service": "^4.4.6", "node-sass": "^4.14.1", "sass-loader": "^8.0.2", + "uglifyjs-webpack-plugin": "^2.2.0", "vue-cli-plugin-i18n": "^1.0.1", "vue-template-compiler": "^2.6.11" }, diff --git a/src/App.vue b/src/App.vue index b3813b3..b76b11f 100644 --- a/src/App.vue +++ b/src/App.vue @@ -6,23 +6,27 @@ - + diff --git a/src/layout/dashboard/DashboardLayout.vue b/src/layout/dashboard/DashboardLayout.vue index c88b113..834cbb0 100644 --- a/src/layout/dashboard/DashboardLayout.vue +++ b/src/layout/dashboard/DashboardLayout.vue @@ -12,6 +12,11 @@ :name="'账号管理'" icon="tim-icons icon-single-02" /> + +
+ + + +

+ 订单持仓最长时间:{{ + accountInfo.MaxOrderHoldTime && secToMin(accountInfo.MaxOrderHoldTime) + }} +

+ +

+ 订单持仓最短时间:{{ + accountInfo.MinOrderHoldTime && secToMin(accountInfo.MinOrderHoldTime) + }} +

+ +

+ 订单最大浮动亏损比:{{ + accountInfo.MaxOrderLossRatio && + accountInfo.MaxOrderLossRatio.toFixed(2) + }}% +

+ +

+ 持仓最大浮动亏损比:{{ + accountInfo.MaxAccountLossRatio && + accountInfo.MaxAccountLossRatio.toFixed(2) + }}% +

+ +

+ 最大盈利金额、订单盈利占比:{{ + accountInfo.MaxOrderProfit && accountInfo.MaxOrderProfit.toFixed(4) + }}({{ + accountInfo.MaxOrderProfitRatio && + accountInfo.MaxOrderProfitRatio.toFixed(2) + }}%) +

+ +

+ 最小盈利金额、订单盈利占比:{{ + accountInfo.MinOrderProfit && accountInfo.MinOrderProfit.toFixed(4) + }}({{ + accountInfo.MinOrderProfitRatio && + accountInfo.MinOrderProfitRatio.toFixed(2) + }}%) +

+
+ + + + diff --git a/src/pages/ReCheck/OrderTable.vue b/src/pages/ReCheck/OrderTable.vue new file mode 100644 index 0000000..003e71a --- /dev/null +++ b/src/pages/ReCheck/OrderTable.vue @@ -0,0 +1,75 @@ + + + diff --git a/src/pages/ReCheck/index.vue b/src/pages/ReCheck/index.vue new file mode 100644 index 0000000..c1eda3e --- /dev/null +++ b/src/pages/ReCheck/index.vue @@ -0,0 +1,651 @@ + + + + diff --git a/src/pages/WinRate/index.vue b/src/pages/WinRate/index.vue index 871e976..232bc22 100644 --- a/src/pages/WinRate/index.vue +++ b/src/pages/WinRate/index.vue @@ -3,45 +3,103 @@ 导入Excel 导入成功:{{ name }}
-
+
- 固定止盈占比 + 固定止盈占比(%)
-
+
- 盈亏占比 + 盈亏占比(%)
- +
+
+ +
+
+ +
+
+ +
+
+ 胜率测试 - + +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ @@ -58,9 +116,9 @@ export default { return { radio: "radio0", name: "", - form: { deadProfitRatio: 0.3, sliderRatio: 0 }, + form: { deadProfitRatio: 0.3, sliderRatio: 0, lostFloatRatio: 0 }, data: [], - result: {} + result: { maxWin: 0, maxLose: 0 } }; }, methods: { @@ -92,24 +150,44 @@ export default { rs(); }); }, - //time open high low close 做多 做空 + //time[0] open[1] high[2] low[3] close[4] 做多 做空 winRateTest() { this.validateForm().then(rs => { let tradeCount = 0; let win = 0; let lose = 0; + let tempWin = 0; + let tempLose = 0; + let maxLose = 0; + let maxWin = 0; + let maxLostRate = 0; + let totalLostRate = 0; for (let i = 0; i < this.data.length; i++) { if (this.isSignal(this.data[i])) { let { up, low } = this.isSignal(this.data[i]); if (!up && !low) { //doing nothing } else { + if (this.form.filterRatio) { + let condition = up + ? (this.data[i][4] - this.data[i][1]) / this.data[i][1] + : (this.data[i][1] - this.data[i][4]) / this.data[i][1]; + // console.log("信号过滤比", condition); + if (condition > this.form.filterRatio / 100) continue; + } tradeCount++; + let result; if (up) { let buyPrice = this.data[i][4] * (1 + this.form.sliderRatio / 100); //收盘价 *滑点比率 - let stopLost = this.data[i][3]; //止损价 + let stopLost = + this.data[i][3] - + Math.abs( + ((this.data[i][4] - this.data[i][1]) * + this.form.lostFloatRatio) / + 100 + ); //止损价 let stopWin; //止盈价 if (this.radio == "radio0") @@ -120,21 +198,26 @@ export default { (buyPrice - stopLost) * (this.form.profitRatio / 100) + buyPrice; - console.log(buyPrice, stopWin, stopLost); - let result = this.reachEnd( + // console.log(buyPrice, stopWin, stopLost); + result = this.reachEnd( 0, i + 1, stopWin, stopLost, - this.data[i][0] + this.data[i][0], + buyPrice ); - if (result == 1) win++; - if (result == -1) lose++; } if (low) { let buyPrice = this.data[i][4] * (1 - this.form.sliderRatio / 100); //收盘价 *滑点比率 - let stopLost = this.data[i][2]; //止损价 + let stopLost = + this.data[i][2] + + Math.abs( + ((this.data[i][1] - this.data[i][4]) * + this.form.lostFloatRatio) / + 100 + ); //止损价 let stopWin; //止盈价 if (this.radio == "radio0") @@ -145,16 +228,29 @@ export default { buyPrice - (buyPrice - stopLost) * (this.form.profitRatio / 100); - console.log(buyPrice, stopWin, stopLost); - let result = this.reachEnd( + // console.log(buyPrice, stopWin, stopLost); + result = this.reachEnd( 1, i + 1, stopWin, stopLost, - this.data[i][0] + this.data[i][0], + buyPrice ); - if (result == 1) win++; - if (result == -1) lose++; + } + if (result == 1) { + win++; + tempLose = 0; + tempWin++; + if (maxWin < tempWin) maxWin = tempWin; + } + if (result < 0) { + lose++; + tempWin = 0; + tempLose++; + if (maxLose < tempLose) maxLose = tempLose; + if (maxLostRate > result) maxLostRate = result; + totalLostRate += result; } } } @@ -162,9 +258,14 @@ export default { this.result = { tradeCount, winRate: ((win / tradeCount) * 100).toFixed(2), - loseRate: ((lose / tradeCount) * 100).toFixed(2) + loseRate: ((lose / tradeCount) * 100).toFixed(2), + maxWin, + maxLose, + totalLostRate: totalLostRate.toFixed(2), + maxLostRate: maxLostRate.toFixed(2), + avgLost: (totalLostRate / lose).toFixed(2) }; - console.log(tradeCount, win); + // console.log(tradeCount, win); }); }, @@ -178,48 +279,52 @@ export default { }, // type: 0 做多 1 做空 - reachEnd(type, index, stopWin, stopLost, timeStamp) { + reachEnd(type, index, stopWin, stopLost, timeStamp, buyPrice) { let result = 0; if (type == 0) { - console.log( - `=====================================================(${timeStamp})做多信号开始===止盈${stopWin}====止损${stopLost}========================================` - ); + // console.log( + // `=====================================================(${timeStamp})做多信号开始===止盈${stopWin}====止损${stopLost}========================================` + // ); //做多 for (let i = index; i < this.data.length; i++) { if (this.data[i][2] > stopWin) { - console.log(`---->触发止盈点`, this.data[i]); + // console.log(`---->触发止盈点`, this.data[i]); result = 1; break; } else if (this.data[i][3] < stopLost) { - console.log(`---->触发止损点`, this.data[i]); - result = -1; + // console.log(`---->触发止损点`, this.data[i]); + let lostPercent = ((stopLost - buyPrice) / buyPrice) * 100; + // console.log("做多亏损比", lostPercent); + result = lostPercent; break; } else { - console.log(`->未触发止盈止损点`, this.data[i]); + // console.log(`->未触发止盈止损点`, this.data[i]); } } } else { - console.log( - `=====================================================(${timeStamp})做空信号开始===止盈${stopWin}====止损${stopLost}========================================` - ); + // console.log( + // `=====================================================(${timeStamp})做空信号开始===止盈${stopWin}====止损${stopLost}========================================` + // ); //做空 for (let i = index; i < this.data.length; i++) { if (this.data[i][3] < stopWin) { - console.log(`---->触发止盈点`, this.data[i]); + // console.log(`---->触发止盈点`, this.data[i]); result = 1; break; } else if (this.data[i][2] > stopLost) { - console.log(`---->触发止损点`, this.data[i]); - result = -1; + // console.log(`---->触发止损点`, this.data[i]); + let lostPercent = ((buyPrice - stopLost) / buyPrice) * 100; + // console.log("做空亏损比", lostPercent, buyPrice, stopLost); + result = lostPercent; break; } else { - console.log(`->未触发止盈止损点`, this.data[i]); + // console.log(`->未触发止盈止损点`, this.data[i]); } } } - console.log( - `=====================================================信号交易结束===止盈${stopWin}====止损${stopLost}========================================` - ); + // console.log( + // `=====================================================信号交易结束===止盈${stopWin}====止损${stopLost}========================================` + // ); return result; }, reachFail() {}, diff --git a/src/router/routes.js b/src/router/routes.js index 77cc51b..b92db23 100644 --- a/src/router/routes.js +++ b/src/router/routes.js @@ -14,7 +14,7 @@ const Robot = () => import("@/pages/Robot"); const Account = () => import("@/pages/Account"); const Edit = () => import("@/pages/Robot/edit.vue"); const WinRate = () => import("@/pages/WinRate"); - +const ReCheck = () => import("@/pages/ReCheck"); const routes = [ { path: "/", @@ -40,6 +40,11 @@ const routes = [ path: "account", name: "account", component: Account + }, + { + path: "reCheck", + name: "reCheck", + component: ReCheck } // { // path: "profile", diff --git a/vue.config.js b/vue.config.js index 5a7829d..3d3e0ba 100644 --- a/vue.config.js +++ b/vue.config.js @@ -1,37 +1,52 @@ -const webpack = require('webpack'); - +const webpack = require("webpack"); +const UglifyJsPlugin = require("uglifyjs-webpack-plugin"); module.exports = { lintOnSave: false, configureWebpack: { // Set up all the aliases we use in our app. resolve: { alias: { - 'chart.js': 'chart.js/dist/Chart.js' + "chart.js": "chart.js/dist/Chart.js" } }, plugins: [ new webpack.optimize.LimitChunkCountPlugin({ maxChunks: 6 }) - ] + ], + optimization: { + minimizer: [ + new UglifyJsPlugin({ + uglifyOptions: { + output: { + comments: false + }, + compress: { + drop_debugger: true, + drop_console: true + } + } + }) + ] + } }, pwa: { - name: 'Vue Black Dashboard', - themeColor: '#344675', - msTileColor: '#344675', - appleMobileWebAppCapable: 'yes', - appleMobileWebAppStatusBarStyle: '#344675' + name: "Vue Black Dashboard", + themeColor: "#344675", + msTileColor: "#344675", + appleMobileWebAppCapable: "yes", + appleMobileWebAppStatusBarStyle: "#344675" }, pluginOptions: { i18n: { - locale: 'en', - fallbackLocale: 'en', - localeDir: 'locales', + locale: "en", + fallbackLocale: "en", + localeDir: "locales", enableInSFC: false } }, css: { // Enable CSS source maps. - sourceMap: process.env.NODE_ENV !== 'production' + sourceMap: process.env.NODE_ENV !== "production" } };