w-trade-solve 1.0.5 → 2.0.2
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/README.md +3 -2
- package/dist/w-trade-solve.umd.js +4 -4
- package/dist/w-trade-solve.umd.js.map +1 -1
- package/docs/calcFitness.mjs.html +1 -1
- package/docs/calcLevelNumTrade.mjs.html +1 -1
- package/docs/cont.mjs.html +2 -2
- package/docs/estimComps.mjs.html +1 -1
- package/docs/estimFinder.mjs.html +1 -1
- package/docs/estimKeys.mjs.html +145 -77
- package/docs/estimPicks.mjs.html +1 -1
- package/docs/genSid.mjs.html +1 -1
- package/docs/genStrategyFileName.mjs.html +14 -10
- package/docs/genTid.mjs.html +1 -1
- package/docs/global.html +192 -22
- package/docs/index.html +1 -1
- package/docs/ott.mjs.html +1 -1
- package/docs/p2r.mjs.html +1 -1
- package/docs/readStrategies.mjs.html +127 -43
- package/g.mjs +3 -2
- package/package.json +2 -2
- package/src/cont.mjs +1 -1
- package/src/estimKeys.mjs +144 -76
- package/src/genStrategyFileName.mjs +12 -8
- package/src/readStrategies.mjs +126 -42
- package/test/unit-estimKeys.test.mjs +222 -5
- package/test/unit-genStrategyFileName.test.mjs +56 -17
- package/test/unit-readStrategies.test.mjs +189 -53
package/docs/global.html
CHANGED
|
@@ -136,7 +136,7 @@
|
|
|
136
136
|
<dt class="tag-description">Description:</dt>
|
|
137
137
|
<dd class="tag-description"><ul class="dummy"><li><p>共用常數</p>
|
|
138
138
|
<p>dlmSeps為tid與sid內各段(mode與各key或各cond)之分隔字串
|
|
139
|
-
dlmPkgs
|
|
139
|
+
dlmPkgs為舊版策略檔名內各段(tid、levelNumTrade、rEquivalentCumuProfitOrLossFinalNormYear)之分隔字串,自genStrategyFileName改採雜湊檔名後僅供readStrategies解析舊格式檔名使用</p></li></ul></dd>
|
|
140
140
|
|
|
141
141
|
|
|
142
142
|
|
|
@@ -184,7 +184,7 @@ dlmPkgs為策略檔名內各段(tid、levelNumTrade、rEquivalentCumuProfitOrLos
|
|
|
184
184
|
<div class="description usertext">
|
|
185
185
|
<p>共用常數</p>
|
|
186
186
|
<p>dlmSeps為tid與sid內各段(mode與各key或各cond)之分隔字串
|
|
187
|
-
dlmPkgs
|
|
187
|
+
dlmPkgs為舊版策略檔名內各段(tid、levelNumTrade、rEquivalentCumuProfitOrLossFinalNormYear)之分隔字串,自genStrategyFileName改採雜湊檔名後僅供readStrategies解析舊格式檔名使用</p>
|
|
188
188
|
</div>
|
|
189
189
|
|
|
190
190
|
|
|
@@ -1841,8 +1841,9 @@ await estimFinder(ott, 'btc', 'BTCUSDT', '4hr', './data/ohlc', './data/param', '
|
|
|
1841
1841
|
<dd class="tag-description"><ul class="dummy"><li><p>針對指定keys率定各key之門檻與止盈止損,求解最佳策略</p>
|
|
1842
1842
|
<p>設計變數為[止損比例, 止盈比例, ...各key之門檻],止損與止盈由opt.thsSl與opt.thsTp給予之百分比清單離散取值
|
|
1843
1843
|
各key門檻取值範圍為[-thLim,thLim]切為thLim<em>20段,並各自平移+vdir與-vdir(vdir=thLim</em>5)為兩組,使解值恆大於0代表'>'條件、恆小於0代表'<'條件,還原時再扣除平移值,故單一設計變數即同時涵蓋大於與小於兩種條件
|
|
1844
|
-
以w-optimization之最佳化函數求解,由opt.methodOml指定演算法,各次計算皆以w-trade-backtest之runStrategy回測並經calcFitness
|
|
1845
|
-
各次計算結果若同時滿足交易次數、勝率與最終等效年化盈虧三門檻,則以genStrategyFileName產生檔名存入fdData
|
|
1844
|
+
以w-optimization之最佳化函數求解,由opt.methodOml指定演算法,各次計算皆以w-trade-backtest之runStrategy回測並經calcFitness計算適應值;亦可由opt.funRunStrategyCustom注入自訂評估核心加速求解(如以w-trade-backtest之buildStrategyFastSession預算first-touch表與因子對位序列),注入僅回傳精簡欄位之核心時可配合opt.useRunStrategyBeforeSave於存檔前重跑完整回測,使落地summary維持完整欄位口徑;存檔前重跑後檔內numTrade、levelNumTrade、tkid、fitness與檔名皆由重跑之summary重新衍生,確保檔名與檔案內容同源一致;重算檔名與原檔名不同(評估核心與重跑結果跨級距)時,對新檔名重做存在檢查、身分驗證與優劣比較,新檔名已有更佳者則放棄本次寫入
|
|
1845
|
+
各次計算結果若同時滿足交易次數、勝率與最終等效年化盈虧三門檻,則以genStrategyFileName產生檔名存入fdData;檔名為tkid(tid+交易次數級距)之純函數,故直接組出檔名查詢既有策略(O(1),不列舉全庫),同tkid已有策略時僅於最終等效年化盈虧更佳時原地覆寫,故同tkid恆僅一檔;覆寫前驗證舊檔內tkid、name與interval與本次一致,不一致代表雜湊碰撞,直接throw以避免無聲覆寫
|
|
1846
|
+
策略檔內容除策略本體(tid、sid、name、symbol、interval、keyOhlc、mode、conds、settings)與summary、fitness外,另落地tkid、numTrade、levelNumTrade、keys與solve區塊(timeStart、timeEnd、methodOml、thNumTrade、thRWin、thREquivalentCumuProfitOrLossFinalNormYear、thsTp、thsSl、timeSolved),使識別與求解條件欄位自足,不依賴檔名
|
|
1846
1847
|
opt除下列各欄位外,其餘欄位皆原樣傳遞至所選之最佳化函數,兩者欄位名稱無重疊,故可一併給予求解設定
|
|
1847
1848
|
各演算法共通之設定為NContiguous(最佳解連續未更新次數上限,預設100)、NRepeat、NCore、ModeOutLimit、UseRepeat、UseImmigration、LocalSearchMethod與funGetBetter、funGenerationBefore、funGenerationAfter三接口;族群數與迴圈數之欄位名稱各演算法不同,RGA與DE為Np與Ng、PSO為Np與Nl、HS為Ns與Ni、ACO為Na與Nl;另各演算法有其專屬超參數,如PSO之psoC1Start、RGA之rgaCrossover、DE之deF、HS之hsHMCR與ACO之acoAlphaStart等
|
|
1848
1849
|
預設之求解量甚大(單一key約需1萬7千次回測),僅需快速試算時可調小族群數與NContiguous
|
|
@@ -1853,7 +1854,7 @@ name、symbol、interval、fdOhlc、fdParam、timeStart、timeEnd、keys、fdDat
|
|
|
1853
1854
|
|
|
1854
1855
|
<dt class="tag-source">Source:</dt>
|
|
1855
1856
|
<dd class="tag-source"><ul class="dummy"><li>
|
|
1856
|
-
<a href="estimKeys.mjs.html">estimKeys.mjs</a>, <a href="estimKeys.mjs.html#
|
|
1857
|
+
<a href="estimKeys.mjs.html">estimKeys.mjs</a>, <a href="estimKeys.mjs.html#line103">line 103</a>
|
|
1857
1858
|
</li></ul></dd>
|
|
1858
1859
|
|
|
1859
1860
|
|
|
@@ -1987,7 +1988,7 @@ console.log(mQuick.stopExecutions) //核心分析次數, 較預設設定大幅
|
|
|
1987
1988
|
</td>
|
|
1988
1989
|
|
|
1989
1990
|
|
|
1990
|
-
<td class="description last"><p>輸入時區時間函數,傳入時間字串回傳dayjs
|
|
1991
|
+
<td class="description last"><p>輸入時區時間函數,傳入時間字串回傳dayjs時間物件,未傳入時回傳當下時間(供solve.timeSolved記錄),可用src/ott.mjs</p></td>
|
|
1991
1992
|
</tr>
|
|
1992
1993
|
|
|
1993
1994
|
|
|
@@ -2655,6 +2656,126 @@ console.log(mQuick.stopExecutions) //核心分析次數, 較預設設定大幅
|
|
|
2655
2656
|
|
|
2656
2657
|
|
|
2657
2658
|
|
|
2659
|
+
<tr>
|
|
2660
|
+
|
|
2661
|
+
<td class="name"><code>funRunStrategyCustom</code></td>
|
|
2662
|
+
|
|
2663
|
+
|
|
2664
|
+
<td class="type">
|
|
2665
|
+
|
|
2666
|
+
|
|
2667
|
+
<span class="param-type">function</span>
|
|
2668
|
+
|
|
2669
|
+
|
|
2670
|
+
|
|
2671
|
+
|
|
2672
|
+
</td>
|
|
2673
|
+
|
|
2674
|
+
|
|
2675
|
+
<td class="attributes">
|
|
2676
|
+
|
|
2677
|
+
<optional><br>
|
|
2678
|
+
|
|
2679
|
+
|
|
2680
|
+
|
|
2681
|
+
|
|
2682
|
+
|
|
2683
|
+
</td>
|
|
2684
|
+
|
|
2685
|
+
|
|
2686
|
+
|
|
2687
|
+
<td class="default">
|
|
2688
|
+
|
|
2689
|
+
<code>null</code>
|
|
2690
|
+
|
|
2691
|
+
</td>
|
|
2692
|
+
|
|
2693
|
+
|
|
2694
|
+
<td class="description last"><p>輸入自訂回測評估async函數,傳入{ott,strategy,funGetSeries}物件,須回傳{summary}且summary至少含numTrade、rWin、uEquityFinal與rEquivalentCumuProfitOrLossFinalNormYear四欄,各欄語義須與runStrategy等值,回傳之準確性由注入端負責;未給時採runStrategy,預設null</p></td>
|
|
2695
|
+
</tr>
|
|
2696
|
+
|
|
2697
|
+
|
|
2698
|
+
|
|
2699
|
+
<tr>
|
|
2700
|
+
|
|
2701
|
+
<td class="name"><code>useRunStrategyBeforeSave</code></td>
|
|
2702
|
+
|
|
2703
|
+
|
|
2704
|
+
<td class="type">
|
|
2705
|
+
|
|
2706
|
+
|
|
2707
|
+
<span class="param-type">Boolean</span>
|
|
2708
|
+
|
|
2709
|
+
|
|
2710
|
+
|
|
2711
|
+
|
|
2712
|
+
</td>
|
|
2713
|
+
|
|
2714
|
+
|
|
2715
|
+
<td class="attributes">
|
|
2716
|
+
|
|
2717
|
+
<optional><br>
|
|
2718
|
+
|
|
2719
|
+
|
|
2720
|
+
|
|
2721
|
+
|
|
2722
|
+
|
|
2723
|
+
</td>
|
|
2724
|
+
|
|
2725
|
+
|
|
2726
|
+
|
|
2727
|
+
<td class="default">
|
|
2728
|
+
|
|
2729
|
+
<code>false</code>
|
|
2730
|
+
|
|
2731
|
+
</td>
|
|
2732
|
+
|
|
2733
|
+
|
|
2734
|
+
<td class="description last"><p>輸入存檔前是否重跑一次回測並以其summary重新衍生檔案內容與檔名布林值,注入僅回傳精簡欄位之評估核心時應設true以維持策略檔欄位口徑,求解搜索仍全程使用自訂函數不受影響,預設false</p></td>
|
|
2735
|
+
</tr>
|
|
2736
|
+
|
|
2737
|
+
|
|
2738
|
+
|
|
2739
|
+
<tr>
|
|
2740
|
+
|
|
2741
|
+
<td class="name"><code>funRunStrategyCustomBeforeSave</code></td>
|
|
2742
|
+
|
|
2743
|
+
|
|
2744
|
+
<td class="type">
|
|
2745
|
+
|
|
2746
|
+
|
|
2747
|
+
<span class="param-type">function</span>
|
|
2748
|
+
|
|
2749
|
+
|
|
2750
|
+
|
|
2751
|
+
|
|
2752
|
+
</td>
|
|
2753
|
+
|
|
2754
|
+
|
|
2755
|
+
<td class="attributes">
|
|
2756
|
+
|
|
2757
|
+
<optional><br>
|
|
2758
|
+
|
|
2759
|
+
|
|
2760
|
+
|
|
2761
|
+
|
|
2762
|
+
|
|
2763
|
+
</td>
|
|
2764
|
+
|
|
2765
|
+
|
|
2766
|
+
|
|
2767
|
+
<td class="default">
|
|
2768
|
+
|
|
2769
|
+
<code>null</code>
|
|
2770
|
+
|
|
2771
|
+
</td>
|
|
2772
|
+
|
|
2773
|
+
|
|
2774
|
+
<td class="description last"><p>輸入存檔前重跑用之自訂回測async函數,介面同opt.funRunStrategyCustom,僅於opt.useRunStrategyBeforeSave為true時生效,未給時採runStrategy,預設null</p></td>
|
|
2775
|
+
</tr>
|
|
2776
|
+
|
|
2777
|
+
|
|
2778
|
+
|
|
2658
2779
|
<tr>
|
|
2659
2780
|
|
|
2660
2781
|
<td class="name"><code>useShowLog</code></td>
|
|
@@ -3748,9 +3869,12 @@ console.log(sid)
|
|
|
3748
3869
|
|
|
3749
3870
|
<dt class="tag-description">Description:</dt>
|
|
3750
3871
|
<dd class="tag-description"><ul class="dummy"><li><p>產生策略儲存檔名</p>
|
|
3751
|
-
<p>檔名為<code>${
|
|
3872
|
+
<p>檔名為<code>${mode}_${levelNumTrade}_${hash}.json</code>,hash為md5(<code>${coin}:${interval}:${tid}:${levelNumTrade}</code>)取前16碼(64bits)
|
|
3752
3873
|
tid由genTid以coin、interval、mode與keys產生,levelNumTrade由calcLevelNumTrade以summary.numTrade產生
|
|
3753
|
-
|
|
3874
|
+
檔名為(coin,interval,tid,levelNumTrade)之純函數且與求解結果(等效年化盈虧)無關,故同tkid恆對應同一檔名,
|
|
3875
|
+
存檔端可直接組出檔名以fsIsFile查詢既有策略(O(1)),不需列舉全庫,且更新為原地覆寫,結構上不會出現同tkid多檔
|
|
3876
|
+
因genTid會剔除<code>${coin}_</code>與<code>${interval}_</code>樣式,不同幣種或週期之同組keys會得到相同tid,故hash輸入需含coin與interval以避免跨幣種/跨週期碰撞
|
|
3877
|
+
採定長雜湊係因NTFS單一檔名段上限為255字元(UTF-16計,LongPathsEnabled無法放寬),keys個數多時舊式<code>${tid} ⊙ ...</code>檔名會超限
|
|
3754
3878
|
settings目前未參與檔名組成</p>
|
|
3755
3879
|
<p>Unit Test: <a href="https://github.com/yuda-lyu/w-trade-solve/blob/master/test/unit-genStrategyFileName.test.mjs">Github</a></p></li></ul></dd>
|
|
3756
3880
|
|
|
@@ -3758,7 +3882,7 @@ settings目前未參與檔名組成</p>
|
|
|
3758
3882
|
|
|
3759
3883
|
<dt class="tag-source">Source:</dt>
|
|
3760
3884
|
<dd class="tag-source"><ul class="dummy"><li>
|
|
3761
|
-
<a href="genStrategyFileName.mjs.html">genStrategyFileName.mjs</a>, <a href="genStrategyFileName.mjs.html#
|
|
3885
|
+
<a href="genStrategyFileName.mjs.html">genStrategyFileName.mjs</a>, <a href="genStrategyFileName.mjs.html#line41">line 41</a>
|
|
3762
3886
|
</li></ul></dd>
|
|
3763
3887
|
|
|
3764
3888
|
|
|
@@ -3813,7 +3937,8 @@ let summary = { numTrade: 30, rEquivalentCumuProfitOrLossFinalNormYear: '31.25%'
|
|
|
3813
3937
|
|
|
3814
3938
|
let fn = genStrategyFileName('btc', '4hr', 'long', keys, settings, summary)
|
|
3815
3939
|
console.log(fn)
|
|
3816
|
-
// => '
|
|
3940
|
+
// => 'long_12_9fce6961e8f56493.json'
|
|
3941
|
+
//tid為'long ║ p_ma_1day', 級距為12, hash為md5('btc:4hr:long ║ p_ma_1day:12')前16碼</code></pre>
|
|
3817
3942
|
|
|
3818
3943
|
|
|
3819
3944
|
|
|
@@ -3980,7 +4105,7 @@ console.log(fn)
|
|
|
3980
4105
|
|
|
3981
4106
|
|
|
3982
4107
|
|
|
3983
|
-
<td class="description last"><p>輸入回測統計摘要物件,需含numTrade(交易次數)
|
|
4108
|
+
<td class="description last"><p>輸入回測統計摘要物件,需含numTrade(交易次數)欄位</p></td>
|
|
3984
4109
|
</tr>
|
|
3985
4110
|
|
|
3986
4111
|
|
|
@@ -4880,8 +5005,11 @@ console.log(p2r(''))
|
|
|
4880
5005
|
<dt class="tag-description">Description:</dt>
|
|
4881
5006
|
<dd class="tag-description"><ul class="dummy"><li><p>讀取儲存策略資料夾內各策略檔資訊</p>
|
|
4882
5007
|
<p>僅列舉fd第1層之檔案,資料夾不列入,fd非資料夾或無任何檔案時回傳空陣列
|
|
4883
|
-
|
|
4884
|
-
|
|
5008
|
+
各檔依opt.fromContent決定解析來源:
|
|
5009
|
+
'filename'為舊式檔名反解: 以主檔名(剔除'.json')依cont.dlmPkgs切段,依序為tid、levelNumTrade與rEquivalentCumuProfitOrLossFinalNormYear,切不出tid者予以略過
|
|
5010
|
+
'content'為讀取檔內json之tid、tkid、levelNumTrade與summary等欄位(即estimKeys所寫出之策略內容),非合法json或無tid欄位者予以略過,因需讀檔故較'filename'慢
|
|
5011
|
+
'auto'(預設)為逐檔判別: 檔名符合genStrategyFileName雜湊格式(<code>${mode}_${levelNumTrade}_${hash16}.json</code>)者走'content',其餘走'filename',故新舊格式混存時皆可列舉
|
|
5012
|
+
tid依cont.dlmSeps切段,首段為mode,其餘為各key所組成之ps
|
|
4885
5013
|
tkid為<code>${tid}:${levelNumTrade}</code>,與estimKeys內用於判斷同組keys與同交易次數級距之組合方式一致</p>
|
|
4886
5014
|
<p>Unit Test: <a href="https://github.com/yuda-lyu/w-trade-solve/blob/master/test/unit-readStrategies.test.mjs">Github</a></p></li></ul></dd>
|
|
4887
5015
|
|
|
@@ -4889,7 +5017,7 @@ tkid為<code>${tid}:${levelNumTrade}</code>,與estimKeys內用於判斷同組k
|
|
|
4889
5017
|
|
|
4890
5018
|
<dt class="tag-source">Source:</dt>
|
|
4891
5019
|
<dd class="tag-source"><ul class="dummy"><li>
|
|
4892
|
-
<a href="readStrategies.mjs.html">readStrategies.mjs</a>, <a href="readStrategies.mjs.html#
|
|
5020
|
+
<a href="readStrategies.mjs.html">readStrategies.mjs</a>, <a href="readStrategies.mjs.html#line67">line 67</a>
|
|
4893
5021
|
</li></ul></dd>
|
|
4894
5022
|
|
|
4895
5023
|
|
|
@@ -4937,20 +5065,22 @@ tkid為<code>${tid}:${levelNumTrade}</code>,與estimKeys內用於判斷同組k
|
|
|
4937
5065
|
<h5 class="h5-examples">Example</h5>
|
|
4938
5066
|
|
|
4939
5067
|
<pre class="prettyprint"><code>import fs from 'fs'
|
|
4940
|
-
import
|
|
5068
|
+
import genStrategyFileName from './src/genStrategyFileName.mjs'
|
|
4941
5069
|
|
|
4942
5070
|
let fd = './tmp/data-strategy'
|
|
4943
5071
|
fs.mkdirSync(fd, { recursive: true })
|
|
4944
5072
|
|
|
4945
|
-
//以genStrategyFileName
|
|
4946
|
-
let
|
|
4947
|
-
|
|
5073
|
+
//以genStrategyFileName之檔名規則儲存策略檔, 檔名為雜湊格式, 識別資訊由檔內json承載
|
|
5074
|
+
let summary = { numTrade: 30, rEquivalentCumuProfitOrLossFinalNormYear: '31.25%' }
|
|
5075
|
+
let fn = genStrategyFileName('btc', '4hr', 'long', ['btc_4hr_ma_1day'], {}, summary)
|
|
5076
|
+
let data = { tid: 'long ║ ma_1day', tkid: 'long ║ ma_1day:12', levelNumTrade: 12, mode: 'long', summary }
|
|
5077
|
+
fs.writeFileSync(`${fd}/${fn}`, JSON.stringify(data), 'utf8')
|
|
4948
5078
|
|
|
4949
5079
|
console.log(readStrategies(fd))
|
|
4950
5080
|
// => [
|
|
4951
5081
|
// {
|
|
4952
|
-
// path: './tmp/data-strategy/
|
|
4953
|
-
// name: '
|
|
5082
|
+
// path: './tmp/data-strategy/long_12_a7578526a1fc57d8.json',
|
|
5083
|
+
// name: 'long_12_a7578526a1fc57d8.json',
|
|
4954
5084
|
// tkid: 'long ║ ma_1day:12',
|
|
4955
5085
|
// tid: 'long ║ ma_1day',
|
|
4956
5086
|
// levelNumTrade: '12',
|
|
@@ -5124,7 +5254,47 @@ console.log(readStrategies(fd))
|
|
|
5124
5254
|
</td>
|
|
5125
5255
|
|
|
5126
5256
|
|
|
5127
|
-
<td class="description last"><p
|
|
5257
|
+
<td class="description last"><p>輸入是否額外提供策略檔內容布林值,為true時各元素額外提供data欄位,內容非合法json時data為null,預設false</p></td>
|
|
5258
|
+
</tr>
|
|
5259
|
+
|
|
5260
|
+
|
|
5261
|
+
|
|
5262
|
+
<tr>
|
|
5263
|
+
|
|
5264
|
+
<td class="name"><code>fromContent</code></td>
|
|
5265
|
+
|
|
5266
|
+
|
|
5267
|
+
<td class="type">
|
|
5268
|
+
|
|
5269
|
+
|
|
5270
|
+
<span class="param-type">String</span>
|
|
5271
|
+
|
|
5272
|
+
|
|
5273
|
+
|
|
5274
|
+
|
|
5275
|
+
</td>
|
|
5276
|
+
|
|
5277
|
+
|
|
5278
|
+
<td class="attributes">
|
|
5279
|
+
|
|
5280
|
+
<optional><br>
|
|
5281
|
+
|
|
5282
|
+
|
|
5283
|
+
|
|
5284
|
+
|
|
5285
|
+
|
|
5286
|
+
</td>
|
|
5287
|
+
|
|
5288
|
+
|
|
5289
|
+
|
|
5290
|
+
<td class="default">
|
|
5291
|
+
|
|
5292
|
+
<code>'auto'</code>
|
|
5293
|
+
|
|
5294
|
+
</td>
|
|
5295
|
+
|
|
5296
|
+
|
|
5297
|
+
<td class="description last"><p>輸入解析來源字串,可選'filename'(由檔名反解)、'content'(讀檔內json欄位)與'auto'(依檔名格式逐檔判別),給予其他值時亦採'auto',預設'auto'</p></td>
|
|
5128
5298
|
</tr>
|
|
5129
5299
|
|
|
5130
5300
|
|
|
@@ -5199,7 +5369,7 @@ console.log(readStrategies(fd))
|
|
|
5199
5369
|
<br class="clear">
|
|
5200
5370
|
|
|
5201
5371
|
<footer>
|
|
5202
|
-
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on
|
|
5372
|
+
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Wed Aug 12 2026 16:01:18 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
|
|
5203
5373
|
</footer>
|
|
5204
5374
|
|
|
5205
5375
|
<script>prettyPrint();</script>
|
package/docs/index.html
CHANGED
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
<br class="clear">
|
|
72
72
|
|
|
73
73
|
<footer>
|
|
74
|
-
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on
|
|
74
|
+
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Wed Aug 12 2026 16:01:18 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
|
|
75
75
|
</footer>
|
|
76
76
|
|
|
77
77
|
<script>prettyPrint();</script>
|
package/docs/ott.mjs.html
CHANGED
|
@@ -124,7 +124,7 @@ export { ott, nowTpeStr, nowTpeStrp }
|
|
|
124
124
|
<br class="clear">
|
|
125
125
|
|
|
126
126
|
<footer>
|
|
127
|
-
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on
|
|
127
|
+
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Wed Aug 12 2026 16:01:18 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
|
|
128
128
|
</footer>
|
|
129
129
|
|
|
130
130
|
<script>prettyPrint();</script>
|
package/docs/p2r.mjs.html
CHANGED
|
@@ -98,7 +98,7 @@ export default p2r
|
|
|
98
98
|
<br class="clear">
|
|
99
99
|
|
|
100
100
|
<footer>
|
|
101
|
-
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on
|
|
101
|
+
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Wed Aug 12 2026 16:01:18 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
|
|
102
102
|
</footer>
|
|
103
103
|
|
|
104
104
|
<script>prettyPrint();</script>
|
|
@@ -50,6 +50,7 @@ import each from 'lodash-es/each.js'
|
|
|
50
50
|
import filter from 'lodash-es/filter.js'
|
|
51
51
|
import get from 'lodash-es/get.js'
|
|
52
52
|
import size from 'lodash-es/size.js'
|
|
53
|
+
import cstr from 'wsemi/src/cstr.mjs'
|
|
53
54
|
import fsIsFolder from 'wsemi/src/fsIsFolder.mjs'
|
|
54
55
|
import fsReadJson from 'wsemi/src/fsReadJson.mjs'
|
|
55
56
|
import fsTreeFolder from 'wsemi/src/fsTreeFolder.mjs'
|
|
@@ -59,37 +60,47 @@ import sep from 'wsemi/src/sep.mjs'
|
|
|
59
60
|
import cont from './cont.mjs'
|
|
60
61
|
|
|
61
62
|
|
|
63
|
+
//ptnFnHash, genStrategyFileName所產生之雜湊檔名樣式`${mode}_${levelNumTrade}_${hash16}.json`
|
|
64
|
+
let ptnFnHash = /^(long|short)_\d+_[0-9a-f]{16}\.json$/
|
|
65
|
+
|
|
66
|
+
|
|
62
67
|
/**
|
|
63
68
|
* 讀取儲存策略資料夾內各策略檔資訊
|
|
64
69
|
*
|
|
65
70
|
* 僅列舉fd第1層之檔案,資料夾不列入,fd非資料夾或無任何檔案時回傳空陣列
|
|
66
|
-
*
|
|
67
|
-
*
|
|
71
|
+
* 各檔依opt.fromContent決定解析來源:
|
|
72
|
+
* 'filename'為舊式檔名反解: 以主檔名(剔除'.json')依cont.dlmPkgs切段,依序為tid、levelNumTrade與rEquivalentCumuProfitOrLossFinalNormYear,切不出tid者予以略過
|
|
73
|
+
* 'content'為讀取檔內json之tid、tkid、levelNumTrade與summary等欄位(即estimKeys所寫出之策略內容),非合法json或無tid欄位者予以略過,因需讀檔故較'filename'慢
|
|
74
|
+
* 'auto'(預設)為逐檔判別: 檔名符合genStrategyFileName雜湊格式(`${mode}_${levelNumTrade}_${hash16}.json`)者走'content',其餘走'filename',故新舊格式混存時皆可列舉
|
|
75
|
+
* tid依cont.dlmSeps切段,首段為mode,其餘為各key所組成之ps
|
|
68
76
|
* tkid為`${tid}:${levelNumTrade}`,與estimKeys內用於判斷同組keys與同交易次數級距之組合方式一致
|
|
69
77
|
*
|
|
70
78
|
* Unit Test: {@link https://github.com/yuda-lyu/w-trade-solve/blob/master/test/unit-readStrategies.test.mjs Github}
|
|
71
79
|
* @function
|
|
72
80
|
* @param {String} fd 輸入儲存策略資料夾字串
|
|
73
81
|
* @param {Object} [opt={}] 輸入設定物件,預設{}
|
|
74
|
-
* @param {Boolean} [opt.readContent=false]
|
|
82
|
+
* @param {Boolean} [opt.readContent=false] 輸入是否額外提供策略檔內容布林值,為true時各元素額外提供data欄位,內容非合法json時data為null,預設false
|
|
83
|
+
* @param {String} [opt.fromContent='auto'] 輸入解析來源字串,可選'filename'(由檔名反解)、'content'(讀檔內json欄位)與'auto'(依檔名格式逐檔判別),給予其他值時亦採'auto',預設'auto'
|
|
75
84
|
* @returns {Array} 回傳策略資訊陣列,各元素為{path,name,tkid,tid,levelNumTrade,rEquivalentCumuProfitOrLossFinalNormYear,mode,ps},opt.readContent為true時額外提供data
|
|
76
85
|
* @example
|
|
77
86
|
*
|
|
78
87
|
* import fs from 'fs'
|
|
79
|
-
* import
|
|
88
|
+
* import genStrategyFileName from './src/genStrategyFileName.mjs'
|
|
80
89
|
*
|
|
81
90
|
* let fd = './tmp/data-strategy'
|
|
82
91
|
* fs.mkdirSync(fd, { recursive: true })
|
|
83
92
|
*
|
|
84
|
-
* //以genStrategyFileName
|
|
85
|
-
* let
|
|
86
|
-
*
|
|
93
|
+
* //以genStrategyFileName之檔名規則儲存策略檔, 檔名為雜湊格式, 識別資訊由檔內json承載
|
|
94
|
+
* let summary = { numTrade: 30, rEquivalentCumuProfitOrLossFinalNormYear: '31.25%' }
|
|
95
|
+
* let fn = genStrategyFileName('btc', '4hr', 'long', ['btc_4hr_ma_1day'], {}, summary)
|
|
96
|
+
* let data = { tid: 'long ║ ma_1day', tkid: 'long ║ ma_1day:12', levelNumTrade: 12, mode: 'long', summary }
|
|
97
|
+
* fs.writeFileSync(`${fd}/${fn}`, JSON.stringify(data), 'utf8')
|
|
87
98
|
*
|
|
88
99
|
* console.log(readStrategies(fd))
|
|
89
100
|
* // => [
|
|
90
101
|
* // {
|
|
91
|
-
* // path: './tmp/data-strategy/
|
|
92
|
-
* // name: '
|
|
102
|
+
* // path: './tmp/data-strategy/long_12_a7578526a1fc57d8.json',
|
|
103
|
+
* // name: 'long_12_a7578526a1fc57d8.json',
|
|
93
104
|
* // tkid: 'long ║ ma_1day:12',
|
|
94
105
|
* // tid: 'long ║ ma_1day',
|
|
95
106
|
* // levelNumTrade: '12',
|
|
@@ -105,6 +116,12 @@ let readStrategies = (fd, opt = {}) => {
|
|
|
105
116
|
//readContent
|
|
106
117
|
let readContent = get(opt, 'readContent', false)
|
|
107
118
|
|
|
119
|
+
//fromContent
|
|
120
|
+
let fromContent = get(opt, 'fromContent', '')
|
|
121
|
+
if (fromContent !== 'filename' && fromContent !== 'content') {
|
|
122
|
+
fromContent = 'auto'
|
|
123
|
+
}
|
|
124
|
+
|
|
108
125
|
//check
|
|
109
126
|
if (!fsIsFolder(fd)) {
|
|
110
127
|
console.log(`invalid fd[${fd}]`)
|
|
@@ -126,44 +143,111 @@ let readStrategies = (fd, opt = {}) => {
|
|
|
126
143
|
let ss = []
|
|
127
144
|
each(vfps, (v) => {
|
|
128
145
|
|
|
129
|
-
//
|
|
130
|
-
let
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
//tid
|
|
134
|
-
let tid = get(qs, 0, '')
|
|
135
|
-
|
|
136
|
-
//check
|
|
137
|
-
if (!isestr(tid)) {
|
|
138
|
-
return true //跳出換下一個
|
|
146
|
+
//useContent, 'auto'依檔名是否符合雜湊格式逐檔判別
|
|
147
|
+
let useContent = fromContent === 'content'
|
|
148
|
+
if (fromContent === 'auto') {
|
|
149
|
+
useContent = ptnFnHash.test(v.name)
|
|
139
150
|
}
|
|
140
151
|
|
|
141
|
-
//levelNumTrade, rEquivalentCumuProfitOrLossFinalNormYear, ps, mode
|
|
142
|
-
let levelNumTrade = get(qs, 1, '')
|
|
143
|
-
let rEquivalentCumuProfitOrLossFinalNormYear = get(qs, 2, '')
|
|
144
|
-
let ps = sep(tid, cont.dlmSeps)
|
|
145
|
-
let mode = get(ps, 0, '')
|
|
146
|
-
ps = drop(ps)
|
|
147
|
-
|
|
148
|
-
//tkid
|
|
149
|
-
let tkid = `${tid}:${levelNumTrade}`
|
|
150
|
-
|
|
151
152
|
//s
|
|
152
|
-
let s =
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
153
|
+
let s = null
|
|
154
|
+
|
|
155
|
+
if (useContent) {
|
|
156
|
+
|
|
157
|
+
//data, 由檔內json取各欄位
|
|
158
|
+
let d = fsReadJson(v.path) //回傳{success}或{error}, 讀取或解析失敗時為null
|
|
159
|
+
let data = get(d, 'success', null)
|
|
160
|
+
|
|
161
|
+
//check
|
|
162
|
+
if (data === null) {
|
|
163
|
+
return true //跳出換下一個
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
//tid
|
|
167
|
+
let tid = get(data, 'tid', '')
|
|
168
|
+
|
|
169
|
+
//check
|
|
170
|
+
if (!isestr(tid)) {
|
|
171
|
+
return true //跳出換下一個
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
//levelNumTrade, 為與檔名反解之回傳格式一致, 轉為字串
|
|
175
|
+
let levelNumTrade = cstr(get(data, 'levelNumTrade', ''))
|
|
176
|
+
|
|
177
|
+
//rEquivalentCumuProfitOrLossFinalNormYear
|
|
178
|
+
let rEquivalentCumuProfitOrLossFinalNormYear = get(data, 'summary.rEquivalentCumuProfitOrLossFinalNormYear', '')
|
|
179
|
+
|
|
180
|
+
//ps, mode
|
|
181
|
+
let ps = sep(tid, cont.dlmSeps)
|
|
182
|
+
let mode = get(ps, 0, '')
|
|
183
|
+
ps = drop(ps)
|
|
184
|
+
|
|
185
|
+
//tkid, 舊內容無tkid欄位時由tid與levelNumTrade組出
|
|
186
|
+
let tkid = get(data, 'tkid', '')
|
|
187
|
+
if (!isestr(tkid)) {
|
|
188
|
+
tkid = `${tid}:${levelNumTrade}`
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
//s
|
|
192
|
+
s = {
|
|
193
|
+
path: v.path,
|
|
194
|
+
name: v.name,
|
|
195
|
+
tkid,
|
|
196
|
+
tid,
|
|
197
|
+
levelNumTrade,
|
|
198
|
+
rEquivalentCumuProfitOrLossFinalNormYear,
|
|
199
|
+
mode,
|
|
200
|
+
ps,
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
//readContent
|
|
204
|
+
if (readContent) {
|
|
205
|
+
s.data = data
|
|
206
|
+
}
|
|
207
|
+
|
|
161
208
|
}
|
|
209
|
+
else {
|
|
210
|
+
|
|
211
|
+
//qs
|
|
212
|
+
let name = replace(v.name, '.json', '')
|
|
213
|
+
let qs = sep(name, cont.dlmPkgs)
|
|
214
|
+
|
|
215
|
+
//tid
|
|
216
|
+
let tid = get(qs, 0, '')
|
|
217
|
+
|
|
218
|
+
//check
|
|
219
|
+
if (!isestr(tid)) {
|
|
220
|
+
return true //跳出換下一個
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
//levelNumTrade, rEquivalentCumuProfitOrLossFinalNormYear, ps, mode
|
|
224
|
+
let levelNumTrade = get(qs, 1, '')
|
|
225
|
+
let rEquivalentCumuProfitOrLossFinalNormYear = get(qs, 2, '')
|
|
226
|
+
let ps = sep(tid, cont.dlmSeps)
|
|
227
|
+
let mode = get(ps, 0, '')
|
|
228
|
+
ps = drop(ps)
|
|
229
|
+
|
|
230
|
+
//tkid
|
|
231
|
+
let tkid = `${tid}:${levelNumTrade}`
|
|
232
|
+
|
|
233
|
+
//s
|
|
234
|
+
s = {
|
|
235
|
+
path: v.path,
|
|
236
|
+
name: v.name,
|
|
237
|
+
tkid,
|
|
238
|
+
tid,
|
|
239
|
+
levelNumTrade,
|
|
240
|
+
rEquivalentCumuProfitOrLossFinalNormYear,
|
|
241
|
+
mode,
|
|
242
|
+
ps,
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
//readContent
|
|
246
|
+
if (readContent) {
|
|
247
|
+
let d = fsReadJson(v.path) //回傳{success}或{error}, 讀取或解析失敗時data為null
|
|
248
|
+
s.data = get(d, 'success', null)
|
|
249
|
+
}
|
|
162
250
|
|
|
163
|
-
//readContent
|
|
164
|
-
if (readContent) {
|
|
165
|
-
let d = fsReadJson(v.path) //回傳{success}或{error}, 讀取或解析失敗時data為null
|
|
166
|
-
s.data = get(d, 'success', null)
|
|
167
251
|
}
|
|
168
252
|
|
|
169
253
|
//push
|
|
@@ -190,7 +274,7 @@ export default readStrategies
|
|
|
190
274
|
<br class="clear">
|
|
191
275
|
|
|
192
276
|
<footer>
|
|
193
|
-
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on
|
|
277
|
+
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Wed Aug 12 2026 16:01:18 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
|
|
194
278
|
</footer>
|
|
195
279
|
|
|
196
280
|
<script>prettyPrint();</script>
|
package/g.mjs
CHANGED
|
@@ -95,9 +95,10 @@ async function test() {
|
|
|
95
95
|
console.log(wts.calcLevelNumTrade(3), wts.calcLevelNumTrade(30), wts.calcLevelNumTrade(300))
|
|
96
96
|
// => 1 12 102
|
|
97
97
|
|
|
98
|
-
//genStrategyFileName, 策略儲存檔名, 為`${
|
|
98
|
+
//genStrategyFileName, 策略儲存檔名, 為`${mode}_${級距}_${雜湊16碼}.json`, 雜湊由coin、interval、tid與級距算出
|
|
99
|
+
// 檔名為tkid之純函數且長度固定, 同tkid恆對應同一檔名, 故存檔端可直查覆寫而不需列舉全庫
|
|
99
100
|
console.log(wts.genStrategyFileName('btc', '4hr', 'long', keys, {}, { numTrade: 30, rEquivalentCumuProfitOrLossFinalNormYear: '31.25%' }))
|
|
100
|
-
// => '
|
|
101
|
+
// => 'long_12_a7578526a1fc57d8.json'
|
|
101
102
|
|
|
102
103
|
//calcFitness, 求解所用之目標函數值, 越小越佳, 由勝率(權重 2)與等效年化盈虧(權重 1)組成
|
|
103
104
|
console.log(wts.calcFitness({ uIni: 1000 }, { numTrade: 30, uEquityFinal: 1200, rWin: '60%', rEquivalentCumuProfitOrLossFinalNormYear: '25%' }))
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "w-trade-solve",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.2",
|
|
4
4
|
"main": "dist/w-trade-solve.umd.js",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"w-data-tdprovide": "^1.0.6",
|
|
7
7
|
"w-optimization": "^1.0.24",
|
|
8
|
-
"w-trade-backtest": "^1.
|
|
8
|
+
"w-trade-backtest": "^1.1.1",
|
|
9
9
|
"wsemi": "^1.8.70"
|
|
10
10
|
},
|
|
11
11
|
"devDependencies": {
|
package/src/cont.mjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* 共用常數
|
|
3
3
|
*
|
|
4
4
|
* dlmSeps為tid與sid內各段(mode與各key或各cond)之分隔字串
|
|
5
|
-
* dlmPkgs
|
|
5
|
+
* dlmPkgs為舊版策略檔名內各段(tid、levelNumTrade、rEquivalentCumuProfitOrLossFinalNormYear)之分隔字串,自genStrategyFileName改採雜湊檔名後僅供readStrategies解析舊格式檔名使用
|
|
6
6
|
*
|
|
7
7
|
* @name cont
|
|
8
8
|
* @const
|