w-trade-solve 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.editorconfig +9 -0
- package/.eslintignore +3 -0
- package/.eslintrc.js +55 -0
- package/.jsdoc +25 -0
- package/README.md +132 -0
- package/SECURITY.md +5 -0
- package/babel.config.js +16 -0
- package/dist/w-trade-solve.umd.js +19 -0
- package/dist/w-trade-solve.umd.js.map +1 -0
- package/docs/calcFitness.mjs.html +205 -0
- package/docs/calcLevelNumTrade.mjs.html +164 -0
- package/docs/cont.mjs.html +94 -0
- package/docs/estimComps.mjs.html +190 -0
- package/docs/estimFinder.mjs.html +197 -0
- package/docs/estimKeys.mjs.html +571 -0
- package/docs/estimPicks.mjs.html +200 -0
- package/docs/fonts/Montserrat/Montserrat-Bold.eot +0 -0
- package/docs/fonts/Montserrat/Montserrat-Bold.ttf +0 -0
- package/docs/fonts/Montserrat/Montserrat-Bold.woff +0 -0
- package/docs/fonts/Montserrat/Montserrat-Bold.woff2 +0 -0
- package/docs/fonts/Montserrat/Montserrat-Regular.eot +0 -0
- package/docs/fonts/Montserrat/Montserrat-Regular.ttf +0 -0
- package/docs/fonts/Montserrat/Montserrat-Regular.woff +0 -0
- package/docs/fonts/Montserrat/Montserrat-Regular.woff2 +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg +978 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.ttf +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff2 +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg +1049 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.ttf +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff2 +0 -0
- package/docs/genSid.mjs.html +125 -0
- package/docs/genStrategyFileName.mjs.html +131 -0
- package/docs/genTid.mjs.html +113 -0
- package/docs/global.html +4932 -0
- package/docs/index.html +84 -0
- package/docs/ott.mjs.html +137 -0
- package/docs/p2r.mjs.html +111 -0
- package/docs/readStrategies.mjs.html +203 -0
- package/docs/scripts/collapse.js +39 -0
- package/docs/scripts/commonNav.js +28 -0
- package/docs/scripts/linenumber.js +25 -0
- package/docs/scripts/nav.js +12 -0
- package/docs/scripts/polyfill.js +4 -0
- package/docs/scripts/prettify/Apache-License-2.0.txt +202 -0
- package/docs/scripts/prettify/lang-css.js +2 -0
- package/docs/scripts/prettify/prettify.js +28 -0
- package/docs/scripts/search.js +99 -0
- package/docs/styles/jsdoc.css +776 -0
- package/docs/styles/prettify.css +80 -0
- package/g.mjs +110 -0
- package/package.json +31 -0
- package/script.txt +19 -0
- package/src/WTradeSolve.mjs +29 -0
- package/src/calcFitness.mjs +133 -0
- package/src/calcLevelNumTrade.mjs +92 -0
- package/src/cont.mjs +22 -0
- package/src/estimComps.mjs +118 -0
- package/src/estimFinder.mjs +125 -0
- package/src/estimKeys.mjs +499 -0
- package/src/estimPicks.mjs +128 -0
- package/src/genSid.mjs +53 -0
- package/src/genStrategyFileName.mjs +59 -0
- package/src/genTid.mjs +41 -0
- package/src/ott.mjs +65 -0
- package/src/p2r.mjs +39 -0
- package/src/readStrategies.mjs +131 -0
- package/test/unit-WTradeSolve.test.mjs +83 -0
- package/test/unit-calcFitness.test.mjs +121 -0
- package/test/unit-calcLevelNumTrade.test.mjs +80 -0
- package/test/unit-estimComps.test.mjs +193 -0
- package/test/unit-estimFinder.test.mjs +184 -0
- package/test/unit-estimKeys.test.mjs +260 -0
- package/test/unit-estimPicks.test.mjs +241 -0
- package/test/unit-genSid.test.mjs +75 -0
- package/test/unit-genStrategyFileName.test.mjs +85 -0
- package/test/unit-genTid.test.mjs +72 -0
- package/test/unit-p2r.test.mjs +51 -0
- package/test/unit-readStrategies.test.mjs +258 -0
- package/test/unit-setup.mjs +119 -0
- package/toolg/addVersion.mjs +4 -0
- package/toolg/cleanFolder.mjs +5 -0
- package/toolg/gDistRollup.mjs +37 -0
- package/toolg/gDocsExams.mjs +48 -0
- package/toolg/modifyReadme.mjs +4 -0
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
|
|
5
|
+
<meta charset="utf-8">
|
|
6
|
+
<title>calcFitness.mjs - Documentation</title>
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
<script src="scripts/prettify/prettify.js"></script>
|
|
10
|
+
<script src="scripts/prettify/lang-css.js"></script>
|
|
11
|
+
<!--[if lt IE 9]>
|
|
12
|
+
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
|
13
|
+
<![endif]-->
|
|
14
|
+
<link type="text/css" rel="stylesheet" href="styles/prettify.css">
|
|
15
|
+
<link type="text/css" rel="stylesheet" href="styles/jsdoc.css">
|
|
16
|
+
<script src="scripts/nav.js" defer></script>
|
|
17
|
+
|
|
18
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
19
|
+
</head>
|
|
20
|
+
<body>
|
|
21
|
+
|
|
22
|
+
<input type="checkbox" id="nav-trigger" class="nav-trigger" />
|
|
23
|
+
<label for="nav-trigger" class="navicon-button x">
|
|
24
|
+
<div class="navicon"></div>
|
|
25
|
+
</label>
|
|
26
|
+
|
|
27
|
+
<label for="nav-trigger" class="overlay"></label>
|
|
28
|
+
|
|
29
|
+
<nav >
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
<h2><a href="index.html">Home</a></h2><h3>Global</h3><ul><li><a href="global.html#calcFitness">calcFitness</a></li><li><a href="global.html#calcLevelNumTrade">calcLevelNumTrade</a></li><li><a href="global.html#cont">cont</a></li><li><a href="global.html#estimComps">estimComps</a></li><li><a href="global.html#estimFinder">estimFinder</a></li><li><a href="global.html#estimKeys">estimKeys</a></li><li><a href="global.html#estimPicks">estimPicks</a></li><li><a href="global.html#genSid">genSid</a></li><li><a href="global.html#genStrategyFileName">genStrategyFileName</a></li><li><a href="global.html#genTid">genTid</a></li><li><a href="global.html#nowTpeStr">nowTpeStr</a></li><li><a href="global.html#nowTpeStrp">nowTpeStrp</a></li><li><a href="global.html#ott">ott</a></li><li><a href="global.html#p2r">p2r</a></li><li><a href="global.html#readStrategies">readStrategies</a></li></ul>
|
|
33
|
+
|
|
34
|
+
</nav>
|
|
35
|
+
|
|
36
|
+
<div id="main">
|
|
37
|
+
|
|
38
|
+
<h1 class="page-title">calcFitness.mjs</h1>
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
<section>
|
|
47
|
+
<article>
|
|
48
|
+
<pre class="prettyprint source linenums"><code>import cint from 'wsemi/src/cint.mjs'
|
|
49
|
+
import p2r from './p2r.mjs'
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* 計算策略適應值fitness
|
|
54
|
+
*
|
|
55
|
+
* 供最佳化求解使用之目標函數值,數值越小代表策略越佳
|
|
56
|
+
* 由勝率與最終等效年化盈虧兩者組成: 勝率rWin限縮至[0,1],等效年化盈虧rEquivalentCumuProfitOrLossFinalNormYear限縮至[0,0.5]再正規化至[0,1],兩者皆轉為越小越好後,以權重2與1加權求和,故無懲罰時fitness落於[0,3]
|
|
57
|
+
* 交易次數為0時加上懲罰值1000000,最終累計盈虧金額(summary.uEquityFinal-settings.uIni)小於等於0時再加上懲罰值1000000,故兩者皆觸發時可達2000000以上
|
|
58
|
+
*
|
|
59
|
+
* Unit Test: {@link https://github.com/yuda-lyu/w-trade-solve/blob/master/test/unit-calcFitness.test.mjs Github}
|
|
60
|
+
* @function
|
|
61
|
+
* @param {Object} settings 輸入策略設定物件,需含uIni(初始資金)欄位
|
|
62
|
+
* @param {Object} summary 輸入回測統計摘要物件,需含numTrade(交易次數)、uEquityFinal(最終權益金額)、rWin(勝率百分比字串)、rEquivalentCumuProfitOrLossFinalNormYear(最終等效年化盈虧百分比字串)欄位
|
|
63
|
+
* @returns {Number} 回傳適應值數值,越小代表策略越佳
|
|
64
|
+
* @example
|
|
65
|
+
*
|
|
66
|
+
* let settings = { uIni: 1000 }
|
|
67
|
+
*
|
|
68
|
+
* //勝率60%, 等效年化盈虧25%(正規化後0.5), fitness = 2*(1-0.6) + 1*(1-0.5) = 1.3
|
|
69
|
+
* let summary = {
|
|
70
|
+
* numTrade: 30,
|
|
71
|
+
* uEquityFinal: 1200,
|
|
72
|
+
* rWin: '60%',
|
|
73
|
+
* rEquivalentCumuProfitOrLossFinalNormYear: '25%',
|
|
74
|
+
* }
|
|
75
|
+
* console.log(calcFitness(settings, summary))
|
|
76
|
+
* // => 1.3
|
|
77
|
+
*
|
|
78
|
+
* //無交易且無獲利時, 兩懲罰值皆觸發
|
|
79
|
+
* let summaryNone = {
|
|
80
|
+
* numTrade: 0,
|
|
81
|
+
* uEquityFinal: 1000,
|
|
82
|
+
* rWin: '',
|
|
83
|
+
* rEquivalentCumuProfitOrLossFinalNormYear: '',
|
|
84
|
+
* }
|
|
85
|
+
* console.log(calcFitness(settings, summaryNone))
|
|
86
|
+
* // => 2000003
|
|
87
|
+
*
|
|
88
|
+
*/
|
|
89
|
+
let calcFitness = (settings, summary) => {
|
|
90
|
+
|
|
91
|
+
//numTrade
|
|
92
|
+
let numTrade = cint(summary.numTrade)
|
|
93
|
+
|
|
94
|
+
//uIni
|
|
95
|
+
let uIni = settings.uIni
|
|
96
|
+
|
|
97
|
+
// //uTradeAllMax
|
|
98
|
+
// let uTradeAllMax = summary.uTradeAllMax
|
|
99
|
+
// // console.log('uTradeAllMax', uTradeAllMax)
|
|
100
|
+
|
|
101
|
+
// //uDrawdownMax
|
|
102
|
+
// let uDrawdownMax = summary.uDrawdownMax
|
|
103
|
+
|
|
104
|
+
//uEquityFinal
|
|
105
|
+
let uEquityFinal = summary.uEquityFinal
|
|
106
|
+
|
|
107
|
+
//uCumuProfitOrLossFinal
|
|
108
|
+
let uCumuProfitOrLossFinal = uEquityFinal - uIni
|
|
109
|
+
// console.log('uCumuProfitOrLossFinal', uCumuProfitOrLossFinal)
|
|
110
|
+
|
|
111
|
+
//rEquivalentCumuProfitOrLossFinalNormYear, 等效年化報酬率
|
|
112
|
+
let rEquivalentCumuProfitOrLossFinalNormYear = p2r(summary.rEquivalentCumuProfitOrLossFinalNormYear)
|
|
113
|
+
rEquivalentCumuProfitOrLossFinalNormYear = Math.min(Math.max(rEquivalentCumuProfitOrLossFinalNormYear, 0), 0.5) //最大限制為年化50% (依實際年化分布調整)
|
|
114
|
+
rEquivalentCumuProfitOrLossFinalNormYear /= 0.5 //正規化最大值1
|
|
115
|
+
|
|
116
|
+
//_rEquivalentCumuProfitOrLossFinalNormYear, 等效年化報酬率越高越好, 須轉換至越低越好
|
|
117
|
+
let _rEquivalentCumuProfitOrLossFinalNormYear = 1 - rEquivalentCumuProfitOrLossFinalNormYear
|
|
118
|
+
// console.log('_rEquivalentCumuProfitOrLossFinalNormYear', _rEquivalentCumuProfitOrLossFinalNormYear)
|
|
119
|
+
|
|
120
|
+
// //rCumuProfitOrLossFinal
|
|
121
|
+
// let rCumuProfitOrLossFinal = p2r(summary.rCumuProfitOrLossFinal)
|
|
122
|
+
|
|
123
|
+
// //_rCumuProfitOrLossFinal, 盈虧越高須轉越低越好
|
|
124
|
+
// let _rCumuProfitOrLossFinal = 3000 - Math.max(rCumuProfitOrLossFinal, 0)
|
|
125
|
+
// if (_rCumuProfitOrLossFinal < 0) {
|
|
126
|
+
// throw new Error(`最終盈虧比例[${_rCumuProfitOrLossFinal}]非預期過高`)
|
|
127
|
+
// }
|
|
128
|
+
// if (rCumuProfitOrLossFinal <= 0) {
|
|
129
|
+
// _rCumuProfitOrLossFinal += 300000 - rCumuProfitOrLossFinal //懲罰值
|
|
130
|
+
// }
|
|
131
|
+
|
|
132
|
+
// //rDrawdownMax
|
|
133
|
+
// let rDrawdownMax = p2r(summary.rDrawdownMax)
|
|
134
|
+
// rDrawdownMax = Math.min(Math.max(rDrawdownMax, 0), 1)
|
|
135
|
+
|
|
136
|
+
// //_rDrawdownMax, 最大回撤率不用轉換, 越低越好
|
|
137
|
+
// let _rDrawdownMax = rDrawdownMax
|
|
138
|
+
|
|
139
|
+
// //rSharpe
|
|
140
|
+
// let rSharpe = w.cdbl(summary.rSharpe)
|
|
141
|
+
|
|
142
|
+
// //_rSharpe, 夏普值越高須轉越低越好
|
|
143
|
+
// let _rSharpe = 5 - Math.min(Math.max(rSharpe, 0), 5) //夏普值理論上可無限大, 故須限制範圍
|
|
144
|
+
// if (_rSharpe < 0) {
|
|
145
|
+
// throw new Error(`夏普值[${rSharpe}]非預期過高`)
|
|
146
|
+
// }
|
|
147
|
+
// if (rSharpe <= 0) {
|
|
148
|
+
// _rSharpe += 100000 - rSharpe //懲罰值
|
|
149
|
+
// }
|
|
150
|
+
|
|
151
|
+
//ratioWin
|
|
152
|
+
let ratioWin = p2r(summary.rWin)
|
|
153
|
+
ratioWin = Math.min(Math.max(ratioWin, 0), 1)
|
|
154
|
+
|
|
155
|
+
//_ratioWin, 勝率越高越好, 須轉換至越低越好
|
|
156
|
+
let _ratioWin = 1 - ratioWin
|
|
157
|
+
|
|
158
|
+
// //ratioKeep
|
|
159
|
+
// let ratioKeep = p2r(summary.rTradeAllMax)
|
|
160
|
+
|
|
161
|
+
//fitness
|
|
162
|
+
let fitness = 0
|
|
163
|
+
// fitness += 3 * _rCumuProfitOrLossFinal
|
|
164
|
+
// fitness += 2 * _rDrawdownMax
|
|
165
|
+
// fitness += 2 * _rSharpe
|
|
166
|
+
fitness += 2 * _ratioWin
|
|
167
|
+
fitness += 1 * _rEquivalentCumuProfitOrLossFinalNormYear
|
|
168
|
+
if (numTrade === 0) {
|
|
169
|
+
fitness += 1000000 //懲罰值
|
|
170
|
+
}
|
|
171
|
+
if (uCumuProfitOrLossFinal <= 0) {
|
|
172
|
+
fitness += 1000000 //懲罰值
|
|
173
|
+
}
|
|
174
|
+
// console.log('fitness', fitness)
|
|
175
|
+
|
|
176
|
+
return fitness
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
export default calcFitness
|
|
181
|
+
</code></pre>
|
|
182
|
+
</article>
|
|
183
|
+
</section>
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
</div>
|
|
191
|
+
|
|
192
|
+
<br class="clear">
|
|
193
|
+
|
|
194
|
+
<footer>
|
|
195
|
+
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Tue Aug 04 2026 23:21:49 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
|
|
196
|
+
</footer>
|
|
197
|
+
|
|
198
|
+
<script>prettyPrint();</script>
|
|
199
|
+
<script src="scripts/polyfill.js"></script>
|
|
200
|
+
<script src="scripts/linenumber.js"></script>
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
</body>
|
|
205
|
+
</html>
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
|
|
5
|
+
<meta charset="utf-8">
|
|
6
|
+
<title>calcLevelNumTrade.mjs - Documentation</title>
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
<script src="scripts/prettify/prettify.js"></script>
|
|
10
|
+
<script src="scripts/prettify/lang-css.js"></script>
|
|
11
|
+
<!--[if lt IE 9]>
|
|
12
|
+
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
|
13
|
+
<![endif]-->
|
|
14
|
+
<link type="text/css" rel="stylesheet" href="styles/prettify.css">
|
|
15
|
+
<link type="text/css" rel="stylesheet" href="styles/jsdoc.css">
|
|
16
|
+
<script src="scripts/nav.js" defer></script>
|
|
17
|
+
|
|
18
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
19
|
+
</head>
|
|
20
|
+
<body>
|
|
21
|
+
|
|
22
|
+
<input type="checkbox" id="nav-trigger" class="nav-trigger" />
|
|
23
|
+
<label for="nav-trigger" class="navicon-button x">
|
|
24
|
+
<div class="navicon"></div>
|
|
25
|
+
</label>
|
|
26
|
+
|
|
27
|
+
<label for="nav-trigger" class="overlay"></label>
|
|
28
|
+
|
|
29
|
+
<nav >
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
<h2><a href="index.html">Home</a></h2><h3>Global</h3><ul><li><a href="global.html#calcFitness">calcFitness</a></li><li><a href="global.html#calcLevelNumTrade">calcLevelNumTrade</a></li><li><a href="global.html#cont">cont</a></li><li><a href="global.html#estimComps">estimComps</a></li><li><a href="global.html#estimFinder">estimFinder</a></li><li><a href="global.html#estimKeys">estimKeys</a></li><li><a href="global.html#estimPicks">estimPicks</a></li><li><a href="global.html#genSid">genSid</a></li><li><a href="global.html#genStrategyFileName">genStrategyFileName</a></li><li><a href="global.html#genTid">genTid</a></li><li><a href="global.html#nowTpeStr">nowTpeStr</a></li><li><a href="global.html#nowTpeStrp">nowTpeStrp</a></li><li><a href="global.html#ott">ott</a></li><li><a href="global.html#p2r">p2r</a></li><li><a href="global.html#readStrategies">readStrategies</a></li></ul>
|
|
33
|
+
|
|
34
|
+
</nav>
|
|
35
|
+
|
|
36
|
+
<div id="main">
|
|
37
|
+
|
|
38
|
+
<h1 class="page-title">calcLevelNumTrade.mjs</h1>
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
<section>
|
|
47
|
+
<article>
|
|
48
|
+
<pre class="prettyprint source linenums"><code>import isnum from 'wsemi/src/isnum.mjs'
|
|
49
|
+
import cint from 'wsemi/src/cint.mjs'
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* 計算交易次數所屬級距代碼levelNumTrade
|
|
54
|
+
*
|
|
55
|
+
* 交易次數過少之策略統計意義不足,過多則屬高頻,故以級距分群,使不同交易次數規模之策略各自保留最佳者
|
|
56
|
+
* 級距對應為: <=0為0,1-5為1,6-9為2,10-24為11,25-49為12,50-74為13,75-99為14,100-249為101,250-499為102,500-749為103,750-999為104,1000-1999為1001,2000-2999為1002,3000-3999為1003,4000-4999為1004,>=5000為100
|
|
57
|
+
* numTrade非數值時throw
|
|
58
|
+
*
|
|
59
|
+
* Unit Test: {@link https://github.com/yuda-lyu/w-trade-solve/blob/master/test/unit-calcLevelNumTrade.test.mjs Github}
|
|
60
|
+
* @function
|
|
61
|
+
* @param {Number} numTrade 輸入交易次數數值
|
|
62
|
+
* @returns {Number} 回傳級距代碼數值
|
|
63
|
+
* @example
|
|
64
|
+
*
|
|
65
|
+
* console.log(calcLevelNumTrade(0))
|
|
66
|
+
* // => 0
|
|
67
|
+
*
|
|
68
|
+
* console.log(calcLevelNumTrade(3))
|
|
69
|
+
* // => 1
|
|
70
|
+
*
|
|
71
|
+
* console.log(calcLevelNumTrade(30))
|
|
72
|
+
* // => 12
|
|
73
|
+
*
|
|
74
|
+
* console.log(calcLevelNumTrade(8000))
|
|
75
|
+
* // => 100
|
|
76
|
+
*
|
|
77
|
+
*/
|
|
78
|
+
let calcLevelNumTrade = (numTrade) => {
|
|
79
|
+
|
|
80
|
+
if (!isnum(numTrade)) {
|
|
81
|
+
throw new Error(`numTrade[${numTrade}] is not a number`)
|
|
82
|
+
}
|
|
83
|
+
numTrade = cint(numTrade)
|
|
84
|
+
|
|
85
|
+
let levelNumTrade = 0
|
|
86
|
+
if (numTrade <= 0) {
|
|
87
|
+
levelNumTrade = 0
|
|
88
|
+
}
|
|
89
|
+
else if (numTrade <= 5) {
|
|
90
|
+
levelNumTrade = 1
|
|
91
|
+
}
|
|
92
|
+
else if (numTrade <= 10 - 1) {
|
|
93
|
+
levelNumTrade = 2
|
|
94
|
+
}
|
|
95
|
+
else if (numTrade <= 25 - 1) {
|
|
96
|
+
levelNumTrade = 11
|
|
97
|
+
}
|
|
98
|
+
else if (numTrade <= 50 - 1) {
|
|
99
|
+
levelNumTrade = 12
|
|
100
|
+
}
|
|
101
|
+
else if (numTrade <= 75 - 1) {
|
|
102
|
+
levelNumTrade = 13
|
|
103
|
+
}
|
|
104
|
+
else if (numTrade <= 100 - 1) {
|
|
105
|
+
levelNumTrade = 14
|
|
106
|
+
}
|
|
107
|
+
else if (numTrade <= 250 - 1) {
|
|
108
|
+
levelNumTrade = 101
|
|
109
|
+
}
|
|
110
|
+
else if (numTrade <= 500 - 1) {
|
|
111
|
+
levelNumTrade = 102
|
|
112
|
+
}
|
|
113
|
+
else if (numTrade <= 750 - 1) {
|
|
114
|
+
levelNumTrade = 103
|
|
115
|
+
}
|
|
116
|
+
else if (numTrade <= 1000 - 1) {
|
|
117
|
+
levelNumTrade = 104
|
|
118
|
+
}
|
|
119
|
+
else if (numTrade <= 2000 - 1) {
|
|
120
|
+
levelNumTrade = 1001
|
|
121
|
+
}
|
|
122
|
+
else if (numTrade <= 3000 - 1) {
|
|
123
|
+
levelNumTrade = 1002
|
|
124
|
+
}
|
|
125
|
+
else if (numTrade <= 4000 - 1) {
|
|
126
|
+
levelNumTrade = 1003
|
|
127
|
+
}
|
|
128
|
+
else if (numTrade <= 5000 - 1) {
|
|
129
|
+
levelNumTrade = 1004
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
levelNumTrade = 100
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return levelNumTrade
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
export default calcLevelNumTrade
|
|
140
|
+
</code></pre>
|
|
141
|
+
</article>
|
|
142
|
+
</section>
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
</div>
|
|
150
|
+
|
|
151
|
+
<br class="clear">
|
|
152
|
+
|
|
153
|
+
<footer>
|
|
154
|
+
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Tue Aug 04 2026 23:21:49 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
|
|
155
|
+
</footer>
|
|
156
|
+
|
|
157
|
+
<script>prettyPrint();</script>
|
|
158
|
+
<script src="scripts/polyfill.js"></script>
|
|
159
|
+
<script src="scripts/linenumber.js"></script>
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
</body>
|
|
164
|
+
</html>
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
|
|
5
|
+
<meta charset="utf-8">
|
|
6
|
+
<title>cont.mjs - Documentation</title>
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
<script src="scripts/prettify/prettify.js"></script>
|
|
10
|
+
<script src="scripts/prettify/lang-css.js"></script>
|
|
11
|
+
<!--[if lt IE 9]>
|
|
12
|
+
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
|
13
|
+
<![endif]-->
|
|
14
|
+
<link type="text/css" rel="stylesheet" href="styles/prettify.css">
|
|
15
|
+
<link type="text/css" rel="stylesheet" href="styles/jsdoc.css">
|
|
16
|
+
<script src="scripts/nav.js" defer></script>
|
|
17
|
+
|
|
18
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
19
|
+
</head>
|
|
20
|
+
<body>
|
|
21
|
+
|
|
22
|
+
<input type="checkbox" id="nav-trigger" class="nav-trigger" />
|
|
23
|
+
<label for="nav-trigger" class="navicon-button x">
|
|
24
|
+
<div class="navicon"></div>
|
|
25
|
+
</label>
|
|
26
|
+
|
|
27
|
+
<label for="nav-trigger" class="overlay"></label>
|
|
28
|
+
|
|
29
|
+
<nav >
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
<h2><a href="index.html">Home</a></h2><h3>Global</h3><ul><li><a href="global.html#calcFitness">calcFitness</a></li><li><a href="global.html#calcLevelNumTrade">calcLevelNumTrade</a></li><li><a href="global.html#cont">cont</a></li><li><a href="global.html#estimComps">estimComps</a></li><li><a href="global.html#estimFinder">estimFinder</a></li><li><a href="global.html#estimKeys">estimKeys</a></li><li><a href="global.html#estimPicks">estimPicks</a></li><li><a href="global.html#genSid">genSid</a></li><li><a href="global.html#genStrategyFileName">genStrategyFileName</a></li><li><a href="global.html#genTid">genTid</a></li><li><a href="global.html#nowTpeStr">nowTpeStr</a></li><li><a href="global.html#nowTpeStrp">nowTpeStrp</a></li><li><a href="global.html#ott">ott</a></li><li><a href="global.html#p2r">p2r</a></li><li><a href="global.html#readStrategies">readStrategies</a></li></ul>
|
|
33
|
+
|
|
34
|
+
</nav>
|
|
35
|
+
|
|
36
|
+
<div id="main">
|
|
37
|
+
|
|
38
|
+
<h1 class="page-title">cont.mjs</h1>
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
<section>
|
|
47
|
+
<article>
|
|
48
|
+
<pre class="prettyprint source linenums"><code>/**
|
|
49
|
+
* 共用常數
|
|
50
|
+
*
|
|
51
|
+
* dlmSeps為tid與sid內各段(mode與各key或各cond)之分隔字串
|
|
52
|
+
* dlmPkgs為策略檔名內各段(tid、levelNumTrade、rEquivalentCumuProfitOrLossFinalNormYear)之分隔字串
|
|
53
|
+
*
|
|
54
|
+
* @name cont
|
|
55
|
+
* @const
|
|
56
|
+
* @type {Object}
|
|
57
|
+
* @example
|
|
58
|
+
*
|
|
59
|
+
* console.log(cont)
|
|
60
|
+
* // => { dlmSeps: ' ║ ', dlmPkgs: ' ⊙ ' }
|
|
61
|
+
*
|
|
62
|
+
*/
|
|
63
|
+
let r = {
|
|
64
|
+
dlmSeps: ' ║ ',
|
|
65
|
+
dlmPkgs: ' ⊙ ',
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
export default r
|
|
70
|
+
</code></pre>
|
|
71
|
+
</article>
|
|
72
|
+
</section>
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
</div>
|
|
80
|
+
|
|
81
|
+
<br class="clear">
|
|
82
|
+
|
|
83
|
+
<footer>
|
|
84
|
+
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Tue Aug 04 2026 23:21:49 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
|
|
85
|
+
</footer>
|
|
86
|
+
|
|
87
|
+
<script>prettyPrint();</script>
|
|
88
|
+
<script src="scripts/polyfill.js"></script>
|
|
89
|
+
<script src="scripts/linenumber.js"></script>
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
</body>
|
|
94
|
+
</html>
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
|
|
5
|
+
<meta charset="utf-8">
|
|
6
|
+
<title>estimComps.mjs - Documentation</title>
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
<script src="scripts/prettify/prettify.js"></script>
|
|
10
|
+
<script src="scripts/prettify/lang-css.js"></script>
|
|
11
|
+
<!--[if lt IE 9]>
|
|
12
|
+
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
|
13
|
+
<![endif]-->
|
|
14
|
+
<link type="text/css" rel="stylesheet" href="styles/prettify.css">
|
|
15
|
+
<link type="text/css" rel="stylesheet" href="styles/jsdoc.css">
|
|
16
|
+
<script src="scripts/nav.js" defer></script>
|
|
17
|
+
|
|
18
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
19
|
+
</head>
|
|
20
|
+
<body>
|
|
21
|
+
|
|
22
|
+
<input type="checkbox" id="nav-trigger" class="nav-trigger" />
|
|
23
|
+
<label for="nav-trigger" class="navicon-button x">
|
|
24
|
+
<div class="navicon"></div>
|
|
25
|
+
</label>
|
|
26
|
+
|
|
27
|
+
<label for="nav-trigger" class="overlay"></label>
|
|
28
|
+
|
|
29
|
+
<nav >
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
<h2><a href="index.html">Home</a></h2><h3>Global</h3><ul><li><a href="global.html#calcFitness">calcFitness</a></li><li><a href="global.html#calcLevelNumTrade">calcLevelNumTrade</a></li><li><a href="global.html#cont">cont</a></li><li><a href="global.html#estimComps">estimComps</a></li><li><a href="global.html#estimFinder">estimFinder</a></li><li><a href="global.html#estimKeys">estimKeys</a></li><li><a href="global.html#estimPicks">estimPicks</a></li><li><a href="global.html#genSid">genSid</a></li><li><a href="global.html#genStrategyFileName">genStrategyFileName</a></li><li><a href="global.html#genTid">genTid</a></li><li><a href="global.html#nowTpeStr">nowTpeStr</a></li><li><a href="global.html#nowTpeStrp">nowTpeStrp</a></li><li><a href="global.html#ott">ott</a></li><li><a href="global.html#p2r">p2r</a></li><li><a href="global.html#readStrategies">readStrategies</a></li></ul>
|
|
33
|
+
|
|
34
|
+
</nav>
|
|
35
|
+
|
|
36
|
+
<div id="main">
|
|
37
|
+
|
|
38
|
+
<h1 class="page-title">estimComps.mjs</h1>
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
<section>
|
|
47
|
+
<article>
|
|
48
|
+
<pre class="prettyprint source linenums"><code>import get from 'lodash-es/get.js'
|
|
49
|
+
import map from 'lodash-es/map.js'
|
|
50
|
+
import size from 'lodash-es/size.js'
|
|
51
|
+
import cint from 'wsemi/src/cint.mjs'
|
|
52
|
+
import isestr from 'wsemi/src/isestr.mjs'
|
|
53
|
+
import randomIntsNdpRange from 'wsemi/src/randomIntsNdpRange.mjs'
|
|
54
|
+
import sep from 'wsemi/src/sep.mjs'
|
|
55
|
+
import estimPicks from './estimPicks.mjs'
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* 依指標組成comps隨機挑選keys,再率定各key之門檻與止盈止損,求解最佳策略
|
|
60
|
+
*
|
|
61
|
+
* comps為以逗號分隔之3個數字字串,依序代表由一般類(keysNorm)、指數類(keysIndex)與成交量類(keysVolumn)各隨機挑選之key個數,例如'2,1,0'代表挑2個一般類、1個指數類與0個成交量類
|
|
62
|
+
* 各類皆以randomIntsNdpRange不重複隨機取樣,故同一comps每次執行所挑之keys不同
|
|
63
|
+
* comps非3段時throw,其餘檢核與分類邏輯同estimPicks
|
|
64
|
+
*
|
|
65
|
+
* Unit Test: {@link https://github.com/yuda-lyu/w-trade-solve/blob/master/test/unit-estimComps.test.mjs Github}
|
|
66
|
+
* @function
|
|
67
|
+
* @param {Function} ott 輸入時區時間函數,傳入時間字串回傳dayjs時間物件,可用src/ott.mjs
|
|
68
|
+
* @param {Object} st 輸入設定物件,需可由opt.keySettings取得name、symbol與interval欄位
|
|
69
|
+
* @param {String} fdOhlc 輸入儲存K線(ohlc)序列資料夾字串
|
|
70
|
+
* @param {String} fdParam 輸入儲存指標參數序列資料夾字串
|
|
71
|
+
* @param {String} timeStart 輸入回測起始時間字串,格式'YYYY-MM-DDTHH:mm:ss'
|
|
72
|
+
* @param {String} timeEnd 輸入回測結束時間字串,格式'YYYY-MM-DDTHH:mm:ss'
|
|
73
|
+
* @param {String} mode 輸入交易方向字串,可選'long'或'short'
|
|
74
|
+
* @param {String} comps 輸入指標組成字串,為逗號分隔之3個數字,例如'2,1,0'
|
|
75
|
+
* @param {String} fdData 輸入儲存策略資料夾字串,不存在時自動建立
|
|
76
|
+
* @param {Object} [opt={}] 輸入設定物件,預設{},全部欄位皆傳遞至estimPicks
|
|
77
|
+
* @returns {Promise} 回傳Promise,resolve為undefined
|
|
78
|
+
* @example
|
|
79
|
+
*
|
|
80
|
+
* import ott from './src/ott.mjs'
|
|
81
|
+
*
|
|
82
|
+
* let st = {
|
|
83
|
+
* btc4hr: { name: 'btc', symbol: 'BTCUSDT', interval: '4hr' },
|
|
84
|
+
* }
|
|
85
|
+
*
|
|
86
|
+
* //comps='2,1,0', 挑2種一般類、1種指數類與0種成交量類
|
|
87
|
+
* await estimComps(ott, st, './data/ohlc', './data/param', '2022-07-01T00:00:00', '2025-04-08T00:00:00', 'long', '2,1,0', './data/strategy', {
|
|
88
|
+
* keySettings: 'btc4hr',
|
|
89
|
+
* })
|
|
90
|
+
*
|
|
91
|
+
*/
|
|
92
|
+
let estimComps = async (ott, st, fdOhlc, fdParam, timeStart, timeEnd, mode, comps, fdData, opt = {}) => {
|
|
93
|
+
|
|
94
|
+
if (!isestr(fdOhlc)) {
|
|
95
|
+
throw new Error(`invalid fdOhlc[${fdOhlc}]`)
|
|
96
|
+
}
|
|
97
|
+
if (!isestr(fdParam)) {
|
|
98
|
+
throw new Error(`invalid fdParam[${fdParam}]`)
|
|
99
|
+
}
|
|
100
|
+
if (!isestr(timeStart)) {
|
|
101
|
+
throw new Error(`invalid timeStart[${timeStart}]`)
|
|
102
|
+
}
|
|
103
|
+
if (!isestr(timeEnd)) {
|
|
104
|
+
throw new Error(`invalid timeEnd[${timeEnd}]`)
|
|
105
|
+
}
|
|
106
|
+
if (mode !== 'long' && mode !== 'short') {
|
|
107
|
+
throw new Error(`invalid mode[${mode}]`)
|
|
108
|
+
}
|
|
109
|
+
if (!isestr(comps)) {
|
|
110
|
+
throw new Error(`invalid comps[${comps}]`)
|
|
111
|
+
}
|
|
112
|
+
if (!isestr(fdData)) {
|
|
113
|
+
throw new Error(`invalid fdData[${fdData}]`)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
//cs, 例如comps='2,1,0', 此為挑2種norm, 1種index, 0種volumn
|
|
117
|
+
let cs = sep(comps, ',')
|
|
118
|
+
if (size(cs) !== 3) {
|
|
119
|
+
throw new Error(`comps[${comps}]非預期`)
|
|
120
|
+
}
|
|
121
|
+
cs = map(cs, cint)
|
|
122
|
+
// console.log('cs', cs)
|
|
123
|
+
|
|
124
|
+
//pkn
|
|
125
|
+
let pkn = (arr, n) => {
|
|
126
|
+
let up = size(arr) - 1
|
|
127
|
+
let ks = randomIntsNdpRange(0, up, n)
|
|
128
|
+
let rs = map(ks, (k) => {
|
|
129
|
+
return get(arr, k)
|
|
130
|
+
})
|
|
131
|
+
return rs
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
//funPickKeys
|
|
135
|
+
let funPickKeys = ({ keysNorm, keysIndex, keysVolumn }) => {
|
|
136
|
+
let keys = []
|
|
137
|
+
if (cs[0] >= 1) {
|
|
138
|
+
keys = [
|
|
139
|
+
...keys,
|
|
140
|
+
...pkn(keysNorm, cs[0]),
|
|
141
|
+
]
|
|
142
|
+
}
|
|
143
|
+
if (cs[1] >= 1) {
|
|
144
|
+
keys = [
|
|
145
|
+
...keys,
|
|
146
|
+
...pkn(keysIndex, cs[1]),
|
|
147
|
+
]
|
|
148
|
+
}
|
|
149
|
+
if (cs[2] >= 1) {
|
|
150
|
+
keys = [
|
|
151
|
+
...keys,
|
|
152
|
+
...pkn(keysVolumn, cs[2]),
|
|
153
|
+
]
|
|
154
|
+
}
|
|
155
|
+
// console.log('keys', keys)
|
|
156
|
+
return keys
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
//estimPicks
|
|
160
|
+
await estimPicks(ott, st, fdOhlc, fdParam, timeStart, timeEnd, mode, funPickKeys, fdData, opt)
|
|
161
|
+
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
export default estimComps
|
|
166
|
+
</code></pre>
|
|
167
|
+
</article>
|
|
168
|
+
</section>
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
</div>
|
|
176
|
+
|
|
177
|
+
<br class="clear">
|
|
178
|
+
|
|
179
|
+
<footer>
|
|
180
|
+
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Tue Aug 04 2026 23:21:49 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
|
|
181
|
+
</footer>
|
|
182
|
+
|
|
183
|
+
<script>prettyPrint();</script>
|
|
184
|
+
<script src="scripts/polyfill.js"></script>
|
|
185
|
+
<script src="scripts/linenumber.js"></script>
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
</body>
|
|
190
|
+
</html>
|