w-trade-backtest 1.0.3 → 1.0.5

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.
Files changed (43) hide show
  1. package/dist/w-trade-backtest.umd.js +8 -8
  2. package/dist/w-trade-backtest.umd.js.map +1 -1
  3. package/docs/buildKLinesTpSl.mjs.html +218 -0
  4. package/docs/calcOrders.mjs.html +2 -2
  5. package/docs/calcOrdersRatio.mjs.html +2 -2
  6. package/docs/calcOrdersSummary.mjs.html +2 -2
  7. package/docs/calcOrdersSummarySimple.mjs.html +2 -2
  8. package/docs/calcSummary.mjs.html +2 -2
  9. package/docs/closeAndSummaryOrders.mjs.html +2 -2
  10. package/docs/genKLinesTpSl.mjs.html +154 -0
  11. package/docs/genReport.mjs.html +2 -2
  12. package/docs/genReportCore.mjs.html +2 -2
  13. package/docs/global.html +2078 -380
  14. package/docs/index.html +2 -2
  15. package/docs/loadKLinesTpSl.mjs.html +189 -0
  16. package/docs/runStrategies.mjs.html +2 -2
  17. package/docs/runStrategiesAndBacktest.mjs.html +224 -0
  18. package/docs/runStrategy.mjs.html +2 -2
  19. package/package.json +1 -1
  20. package/src/WTradeBacktest.mjs +8 -0
  21. package/src/buildKLinesTpSl.mjs +146 -0
  22. package/src/genKLinesTpSl.mjs +82 -0
  23. package/src/loadKLinesTpSl.mjs +117 -0
  24. package/src/runStrategiesAndBacktest.mjs +152 -0
  25. package/test/unit-WTradeBacktest.test.mjs +23 -529
  26. package/test/unit-buildKLinesTpSl.test.mjs +98 -0
  27. package/test/unit-calcOrders.test.mjs +60 -0
  28. package/test/unit-calcOrdersRatio.test.mjs +39 -0
  29. package/test/unit-calcOrdersSummary.test.mjs +71 -0
  30. package/test/unit-calcOrdersSummarySimple.test.mjs +30 -0
  31. package/test/unit-calcSummary.test.mjs +30 -0
  32. package/test/unit-closeAndSummaryOrders.test.mjs +53 -0
  33. package/test/unit-genKLinesTpSl.test.mjs +46 -0
  34. package/test/unit-genReport.test.mjs +113 -0
  35. package/test/unit-genReportCore.test.mjs +39 -0
  36. package/test/unit-loadKLinesTpSl.test.mjs +158 -0
  37. package/test/unit-ott.test.mjs +20 -0
  38. package/test/unit-runStrategies.test.mjs +30 -0
  39. package/test/unit-runStrategiesAndBacktest.test.mjs +114 -0
  40. package/test/unit-runStrategy.test.mjs +53 -0
  41. package/test/unit-setup.mjs +120 -0
  42. package/test/unit-writeJson.test.mjs +29 -0
  43. package/test/unit-writeTxt.test.mjs +27 -0
package/docs/global.html CHANGED
@@ -29,7 +29,7 @@
29
29
  <nav >
30
30
 
31
31
 
32
- <h2><a href="index.html">Home</a></h2><h3>Global</h3><ul><li><a href="global.html#calcOrders">calcOrders</a></li><li><a href="global.html#calcOrdersRatio">calcOrdersRatio</a></li><li><a href="global.html#calcOrdersSummary">calcOrdersSummary</a></li><li><a href="global.html#calcOrdersSummarySimple">calcOrdersSummarySimple</a></li><li><a href="global.html#calcSummary">calcSummary</a></li><li><a href="global.html#closeAndSummaryOrders">closeAndSummaryOrders</a></li><li><a href="global.html#genReport">genReport</a></li><li><a href="global.html#genReportCore">genReportCore</a></li><li><a href="global.html#runStrategies">runStrategies</a></li><li><a href="global.html#runStrategy">runStrategy</a></li></ul>
32
+ <h2><a href="index.html">Home</a></h2><h3>Global</h3><ul><li><a href="global.html#buildKLinesTpSl">buildKLinesTpSl</a></li><li><a href="global.html#calcOrders">calcOrders</a></li><li><a href="global.html#calcOrdersRatio">calcOrdersRatio</a></li><li><a href="global.html#calcOrdersSummary">calcOrdersSummary</a></li><li><a href="global.html#calcOrdersSummarySimple">calcOrdersSummarySimple</a></li><li><a href="global.html#calcSummary">calcSummary</a></li><li><a href="global.html#closeAndSummaryOrders">closeAndSummaryOrders</a></li><li><a href="global.html#genKLinesTpSl">genKLinesTpSl</a></li><li><a href="global.html#genReport">genReport</a></li><li><a href="global.html#genReportCore">genReportCore</a></li><li><a href="global.html#loadKLinesTpSl">loadKLinesTpSl</a></li><li><a href="global.html#runStrategies">runStrategies</a></li><li><a href="global.html#runStrategiesAndBacktest">runStrategiesAndBacktest</a></li><li><a href="global.html#runStrategy">runStrategy</a></li></ul>
33
33
 
34
34
  </nav>
35
35
 
@@ -130,7 +130,7 @@
130
130
 
131
131
 
132
132
 
133
- <h4 class="name" id="calcOrders"><span class="type-signature type-signature-async">(async) </span>calcOrders<span class="signature">(arrOhlc, orders, opt<span class="signature-attributes">opt</span>)</span><span class="type-signature"> &rarr; {Promise}</span></h4>
133
+ <h4 class="name" id="buildKLinesTpSl"><span class="type-signature type-signature-async">(async) </span>buildKLinesTpSl<span class="signature">(fdOhlc, fdParam, fpJson, opt<span class="signature-attributes">opt</span>)</span><span class="type-signature"> &rarr; {Promise}</span></h4>
134
134
 
135
135
 
136
136
 
@@ -140,17 +140,19 @@
140
140
  <dl class="details">
141
141
 
142
142
  <dt class="tag-description">Description:</dt>
143
- <dd class="tag-description"><ul class="dummy"><li><p>結算訂單,依K線序列判斷各下單之止盈止損觸發並計算盈虧</p>
144
- <p>各單僅檢查time大於timeStart之K棒,long以Low&lt;=priceStopLoss先判止損、High&gt;=priceTakeProfit判止盈,short以High&gt;=priceStopLoss先判止損、Low&lt;=priceTakeProfit判止盈
145
- long盈虧為uTrade*(priceEnd/priceStart)-uTrade-2<em>uFee,short盈虧為(priceStart-priceEnd)</em>(uTrade/priceStart)-2*uFee
146
- 依timeStart排序逐單累計uCumuProfitOrLoss與uEquity(自uIni起算),modeResult為盈虧&lt;0時'loss'否則'profit',未觸發止盈止損者維持原單(未平倉)</p>
143
+ <dd class="tag-description"><ul class="dummy"><li><p>建置各K線與各止盈止損組合之先觸結果快取檔</p>
144
+ <p>以w-data-tdprovide讀取fdOhlc與fdParam資料夾內keyOhlc序列,取ts至te範圍K線後,逐一組合modes與tps呼叫genKLinesTpSl
145
+ 各組合以<code>${mode}_${tpsl}</code>為key存入各根K線,win為1(止盈先觸)、0(止損先觸)或-1(至區間末仍未結)
146
+ timeEnd於建置時由hold位移換算為絕對時間,故下游查表即得而不需位置索引,未結者為null
147
+ 僅存win、timeEnd與各根close,盈虧由下游loadKLinesTpSl之ordersFromBars以close與手續費重算
148
+ fdOhlc或fdParam非資料夾、fpJson或opt.keyOhlc非有效字串、opt.ts或opt.te非時間字串時throw</p>
147
149
  <p>Unit Test: <a href="https://github.com/yuda-lyu/w-trade-backtest/blob/master/test/unit-WTradeBacktest.test.mjs">Github</a></p></li></ul></dd>
148
150
 
149
151
 
150
152
 
151
153
  <dt class="tag-source">Source:</dt>
152
154
  <dd class="tag-source"><ul class="dummy"><li>
153
- <a href="calcOrders.mjs.html">calcOrders.mjs</a>, <a href="calcOrders.mjs.html#line69">line 69</a>
155
+ <a href="buildKLinesTpSl.mjs.html">buildKLinesTpSl.mjs</a>, <a href="buildKLinesTpSl.mjs.html#line72">line 72</a>
154
156
  </li></ul></dd>
155
157
 
156
158
 
@@ -197,7 +199,9 @@ long盈虧為uTrade*(priceEnd/priceStart)-uTrade-2<em>uFee,short盈虧為(pric
197
199
 
198
200
  <h5 class="h5-examples">Example</h5>
199
201
 
200
- <pre class="prettyprint"><code>let arrOhlc = [
202
+ <pre class="prettyprint"><code>import fs from 'fs'
203
+
204
+ let arrOhlc = [
201
205
  { time: '2020-01-01T00:00:00', Open: 100, High: 101, Low: 99, Close: 100 },
202
206
  { time: '2020-01-01T04:00:00', Open: 100, High: 106, Low: 100, Close: 105 },
203
207
  { time: '2020-01-01T08:00:00', Open: 105, High: 107, Low: 102, Close: 103 },
@@ -206,40 +210,31 @@ long盈虧為uTrade*(priceEnd/priceStart)-uTrade-2<em>uFee,short盈虧為(pric
206
210
  { time: '2020-01-01T20:00:00', Open: 93, High: 99, Low: 95, Close: 97 },
207
211
  ]
208
212
 
209
- let orders = [{
210
- mode: 'long',
211
- timeStart: '2020-01-01T00:00:00',
212
- priceStart: 100,
213
- uTrade: 100,
214
- priceTakeProfit: 105,
215
- priceStopLoss: 97,
216
- timeEnd: '',
217
- priceEnd: '',
218
- modeResult: '',
219
- uFee: 0.05,
220
- }]
213
+ //建立數據資料夾, fdOhlc放K線序列, fdParam放指標參數序列
214
+ fs.mkdirSync('./data-ohlc', { recursive: true })
215
+ fs.mkdirSync('./data-param', { recursive: true })
216
+ fs.writeFileSync('./data-ohlc/btc.json', JSON.stringify(arrOhlc), 'utf8')
221
217
 
222
- calcOrders(arrOhlc, orders, { uIni: 1000 })
223
- .then((rs) => {
224
- console.log(rs[0])
225
- // => {
226
- // mode: 'long',
227
- // timeStart: '2020-01-01T00:00:00',
228
- // priceStart: 100,
229
- // uTrade: 100,
230
- // priceTakeProfit: 105,
231
- // priceStopLoss: 97,
232
- // timeEnd: '2020-01-01T04:00:00',
233
- // priceEnd: 105,
234
- // modeResult: 'profit',
235
- // uFee: 0.05,
236
- // uProfitOrLoss: 4.9,
237
- // rProfitOrLoss: 0.049,
238
- // uCumuProfitOrLoss: 4.9,
239
- // rCumuProfitOrLoss: '0.49%',
240
- // uEquity: 1004.9
241
- // }
242
- })</code></pre>
218
+ let r = await buildKLinesTpSl('./data-ohlc', './data-param', './cache/kltpsl.json', {
219
+ keyOhlc: 'btc',
220
+ ts: '2020-01-01T00:00:00',
221
+ te: '2020-01-01T20:00:00',
222
+ tps: [5],
223
+ modes: ['long'],
224
+ })
225
+ console.log(r.meta)
226
+ // => {
227
+ // keyOhlc: 'btc',
228
+ // ts: '2020-01-01T00:00:00',
229
+ // te: '2020-01-01T20:00:00',
230
+ // tps: [ 5 ],
231
+ // modes: [ 'long' ],
232
+ // nBars: 6
233
+ // }
234
+ console.log(r.bars['2020-01-01T00:00:00'])
235
+ // => { close: 100, long_5: { win: 1, timeEnd: '2020-01-01T04:00:00' } }
236
+ console.log(r.bars['2020-01-01T12:00:00'])
237
+ // => { close: 95, long_5: { win: -1, timeEnd: null } }</code></pre>
243
238
 
244
239
 
245
240
 
@@ -273,13 +268,13 @@ calcOrders(arrOhlc, orders, { uIni: 1000 })
273
268
 
274
269
  <tr>
275
270
 
276
- <td class="name"><code>arrOhlc</code></td>
271
+ <td class="name"><code>fdOhlc</code></td>
277
272
 
278
273
 
279
274
  <td class="type">
280
275
 
281
276
 
282
- <span class="param-type">Array</span>
277
+ <span class="param-type">String</span>
283
278
 
284
279
 
285
280
 
@@ -302,20 +297,20 @@ calcOrders(arrOhlc, orders, { uIni: 1000 })
302
297
  </td>
303
298
 
304
299
 
305
- <td class="description last"><p>輸入K線陣列,各元素需含time、High、Low欄位</p></td>
300
+ <td class="description last"><p>輸入儲存K線(ohlc)序列資料夾字串,各序列以<code>${key}.json</code>儲存</p></td>
306
301
  </tr>
307
302
 
308
303
 
309
304
 
310
305
  <tr>
311
306
 
312
- <td class="name"><code>orders</code></td>
307
+ <td class="name"><code>fdParam</code></td>
313
308
 
314
309
 
315
310
  <td class="type">
316
311
 
317
312
 
318
- <span class="param-type">Array</span>
313
+ <span class="param-type">String</span>
319
314
 
320
315
 
321
316
 
@@ -338,7 +333,43 @@ calcOrders(arrOhlc, orders, { uIni: 1000 })
338
333
  </td>
339
334
 
340
335
 
341
- <td class="description last"><p>輸入下單陣列,各元素需含mode('long'或'short')、timeStart、priceStart、uTrade、priceTakeProfit、priceStopLoss、uFee欄位</p></td>
336
+ <td class="description last"><p>輸入儲存指標參數序列資料夾字串</p></td>
337
+ </tr>
338
+
339
+
340
+
341
+ <tr>
342
+
343
+ <td class="name"><code>fpJson</code></td>
344
+
345
+
346
+ <td class="type">
347
+
348
+
349
+ <span class="param-type">String</span>
350
+
351
+
352
+
353
+
354
+ </td>
355
+
356
+
357
+ <td class="attributes">
358
+
359
+
360
+
361
+
362
+
363
+ </td>
364
+
365
+
366
+
367
+ <td class="default">
368
+
369
+ </td>
370
+
371
+
372
+ <td class="description last"><p>輸入輸出快取json檔案路徑字串,資料夾不存在時自動建立</p></td>
342
373
  </tr>
343
374
 
344
375
 
@@ -408,13 +439,121 @@ calcOrders(arrOhlc, orders, { uIni: 1000 })
408
439
 
409
440
  <tr>
410
441
 
411
- <td class="name"><code>uIni</code></td>
442
+ <td class="name"><code>keyOhlc</code></td>
412
443
 
413
444
 
414
445
  <td class="type">
415
446
 
416
447
 
417
- <span class="param-type">Number</span>
448
+ <span class="param-type">String</span>
449
+
450
+
451
+
452
+
453
+ </td>
454
+
455
+
456
+ <td class="attributes">
457
+
458
+
459
+
460
+
461
+
462
+ </td>
463
+
464
+
465
+
466
+ <td class="default">
467
+
468
+ </td>
469
+
470
+
471
+ <td class="description last"><p>輸入K線序列key字串</p></td>
472
+ </tr>
473
+
474
+
475
+
476
+ <tr>
477
+
478
+ <td class="name"><code>ts</code></td>
479
+
480
+
481
+ <td class="type">
482
+
483
+
484
+ <span class="param-type">String</span>
485
+
486
+
487
+
488
+
489
+ </td>
490
+
491
+
492
+ <td class="attributes">
493
+
494
+
495
+
496
+
497
+
498
+ </td>
499
+
500
+
501
+
502
+ <td class="default">
503
+
504
+ </td>
505
+
506
+
507
+ <td class="description last"><p>輸入起始秒時間字串</p></td>
508
+ </tr>
509
+
510
+
511
+
512
+ <tr>
513
+
514
+ <td class="name"><code>te</code></td>
515
+
516
+
517
+ <td class="type">
518
+
519
+
520
+ <span class="param-type">String</span>
521
+
522
+
523
+
524
+
525
+ </td>
526
+
527
+
528
+ <td class="attributes">
529
+
530
+
531
+
532
+
533
+
534
+ </td>
535
+
536
+
537
+
538
+ <td class="default">
539
+
540
+ </td>
541
+
542
+
543
+ <td class="description last"><p>輸入結束秒時間字串</p></td>
544
+ </tr>
545
+
546
+
547
+
548
+ <tr>
549
+
550
+ <td class="name"><code>tps</code></td>
551
+
552
+
553
+ <td class="type">
554
+
555
+
556
+ <span class="param-type">Array</span>
418
557
 
419
558
 
420
559
 
@@ -436,12 +575,52 @@ calcOrders(arrOhlc, orders, { uIni: 1000 })
436
575
 
437
576
  <td class="default">
438
577
 
439
- <code>1000</code>
578
+ <code>[4,5,6,7,8,9,10]</code>
440
579
 
441
580
  </td>
442
581
 
443
582
 
444
- <td class="description last"><p>輸入初始資金數字,預設1000</p></td>
583
+ <td class="description last"><p>輸入止盈止損百分比數值陣列,如5代表止盈與止損皆5%,預設[4,5,6,7,8,9,10]</p></td>
584
+ </tr>
585
+
586
+
587
+
588
+ <tr>
589
+
590
+ <td class="name"><code>modes</code></td>
591
+
592
+
593
+ <td class="type">
594
+
595
+
596
+ <span class="param-type">Array</span>
597
+
598
+
599
+
600
+
601
+ </td>
602
+
603
+
604
+ <td class="attributes">
605
+
606
+ &lt;optional><br>
607
+
608
+
609
+
610
+
611
+
612
+ </td>
613
+
614
+
615
+
616
+ <td class="default">
617
+
618
+ <code>['long','short']</code>
619
+
620
+ </td>
621
+
622
+
623
+ <td class="description last"><p>輸入交易方向字串陣列,預設['long','short']</p></td>
445
624
  </tr>
446
625
 
447
626
 
@@ -474,7 +653,7 @@ calcOrders(arrOhlc, orders, { uIni: 1000 })
474
653
 
475
654
 
476
655
  <div class="param-desc">
477
- <p>回傳Promise,resolve為結算後訂單陣列</p>
656
+ <p>回傳Promise,resolve為{meta,bars}物件,meta內含keyOhlc、ts、te、tps、modes與nBars(K線根數),bars以進場時間為key,各值內含close與各<code>${mode}_${tpsl}</code>之{win,timeEnd},並同步寫出至fpJson</p>
478
657
  </div>
479
658
 
480
659
 
@@ -501,7 +680,7 @@ calcOrders(arrOhlc, orders, { uIni: 1000 })
501
680
 
502
681
 
503
682
 
504
- <h4 class="name" id="calcOrdersRatio"><span class="type-signature"></span>calcOrdersRatio<span class="signature">(ott, orders)</span><span class="type-signature"> &rarr; {Array}</span></h4>
683
+ <h4 class="name" id="calcOrders"><span class="type-signature type-signature-async">(async) </span>calcOrders<span class="signature">(arrOhlc, orders, opt<span class="signature-attributes">opt</span>)</span><span class="type-signature"> &rarr; {Promise}</span></h4>
505
684
 
506
685
 
507
686
 
@@ -511,16 +690,17 @@ calcOrders(arrOhlc, orders, { uIni: 1000 })
511
690
  <dl class="details">
512
691
 
513
692
  <dt class="tag-description">Description:</dt>
514
- <dd class="tag-description"><ul class="dummy"><li><p>計算各已平倉訂單之持倉天數與等效日盈虧比例</p>
515
- <p>dayHold以timeStart與timeEnd之日期差+1計算,rProfitOrLossDay為(1+rProfitOrLoss)^(1/dayHold)-1
516
- modeResult非有效字串(未平倉)之訂單不計算</p>
693
+ <dd class="tag-description"><ul class="dummy"><li><p>結算訂單,依K線序列判斷各下單之止盈止損觸發並計算盈虧</p>
694
+ <p>各單僅檢查time大於timeStart之K棒,long以Low&lt;=priceStopLoss先判止損、High&gt;=priceTakeProfit判止盈,short以High&gt;=priceStopLoss先判止損、Low&lt;=priceTakeProfit判止盈
695
+ long盈虧為uTrade*(priceEnd/priceStart)-uTrade-2<em>uFee,short盈虧為(priceStart-priceEnd)</em>(uTrade/priceStart)-2*uFee
696
+ 依timeStart排序逐單累計uCumuProfitOrLoss與uEquity(自uIni起算),modeResult為盈虧&lt;0時'loss'否則'profit',未觸發止盈止損者維持原單(未平倉)</p>
517
697
  <p>Unit Test: <a href="https://github.com/yuda-lyu/w-trade-backtest/blob/master/test/unit-WTradeBacktest.test.mjs">Github</a></p></li></ul></dd>
518
698
 
519
699
 
520
700
 
521
701
  <dt class="tag-source">Source:</dt>
522
702
  <dd class="tag-source"><ul class="dummy"><li>
523
- <a href="calcOrdersRatio.mjs.html">calcOrdersRatio.mjs</a>, <a href="calcOrdersRatio.mjs.html#line35">line 35</a>
703
+ <a href="calcOrders.mjs.html">calcOrders.mjs</a>, <a href="calcOrders.mjs.html#line69">line 69</a>
524
704
  </li></ul></dd>
525
705
 
526
706
 
@@ -567,21 +747,49 @@ modeResult非有效字串(未平倉)之訂單不計算</p>
567
747
 
568
748
  <h5 class="h5-examples">Example</h5>
569
749
 
570
- <pre class="prettyprint"><code>let orders = calcOrdersRatio(ott, [{
571
- modeResult: 'profit',
572
- timeStart: '2020-01-01T20:00:00',
573
- timeEnd: '2020-01-03T04:00:00',
574
- rProfitOrLoss: 0.331,
575
- }])
576
- console.log(orders[0])
577
- // => {
578
- // modeResult: 'profit',
579
- // timeStart: '2020-01-01T20:00:00',
580
- // timeEnd: '2020-01-03T04:00:00',
581
- // rProfitOrLoss: 0.331,
582
- // dayHold: 3,
583
- // rProfitOrLossDay: 0.10000000000000009
584
- // }</code></pre>
750
+ <pre class="prettyprint"><code>let arrOhlc = [
751
+ { time: '2020-01-01T00:00:00', Open: 100, High: 101, Low: 99, Close: 100 },
752
+ { time: '2020-01-01T04:00:00', Open: 100, High: 106, Low: 100, Close: 105 },
753
+ { time: '2020-01-01T08:00:00', Open: 105, High: 107, Low: 102, Close: 103 },
754
+ { time: '2020-01-01T12:00:00', Open: 103, High: 104, Low: 94, Close: 95 },
755
+ { time: '2020-01-01T16:00:00', Open: 95, High: 98, Low: 92, Close: 93 },
756
+ { time: '2020-01-01T20:00:00', Open: 93, High: 99, Low: 95, Close: 97 },
757
+ ]
758
+
759
+ let orders = [{
760
+ mode: 'long',
761
+ timeStart: '2020-01-01T00:00:00',
762
+ priceStart: 100,
763
+ uTrade: 100,
764
+ priceTakeProfit: 105,
765
+ priceStopLoss: 97,
766
+ timeEnd: '',
767
+ priceEnd: '',
768
+ modeResult: '',
769
+ uFee: 0.05,
770
+ }]
771
+
772
+ calcOrders(arrOhlc, orders, { uIni: 1000 })
773
+ .then((rs) => {
774
+ console.log(rs[0])
775
+ // => {
776
+ // mode: 'long',
777
+ // timeStart: '2020-01-01T00:00:00',
778
+ // priceStart: 100,
779
+ // uTrade: 100,
780
+ // priceTakeProfit: 105,
781
+ // priceStopLoss: 97,
782
+ // timeEnd: '2020-01-01T04:00:00',
783
+ // priceEnd: 105,
784
+ // modeResult: 'profit',
785
+ // uFee: 0.05,
786
+ // uProfitOrLoss: 4.9,
787
+ // rProfitOrLoss: 0.049,
788
+ // uCumuProfitOrLoss: 4.9,
789
+ // rCumuProfitOrLoss: '0.49%',
790
+ // uEquity: 1004.9
791
+ // }
792
+ })</code></pre>
585
793
 
586
794
 
587
795
 
@@ -599,8 +807,12 @@ console.log(orders[0])
599
807
  <th>Type</th>
600
808
 
601
809
 
810
+ <th>Attributes</th>
811
+
602
812
 
603
813
 
814
+ <th>Default</th>
815
+
604
816
 
605
817
  <th class="last">Description</th>
606
818
  </tr>
@@ -611,13 +823,13 @@ console.log(orders[0])
611
823
 
612
824
  <tr>
613
825
 
614
- <td class="name"><code>ott</code></td>
826
+ <td class="name"><code>arrOhlc</code></td>
615
827
 
616
828
 
617
829
  <td class="type">
618
830
 
619
831
 
620
- <span class="param-type">function</span>
832
+ <span class="param-type">Array</span>
621
833
 
622
834
 
623
835
 
@@ -625,10 +837,22 @@ console.log(orders[0])
625
837
  </td>
626
838
 
627
839
 
840
+ <td class="attributes">
841
+
842
+
843
+
844
+
845
+
846
+ </td>
847
+
628
848
 
629
849
 
850
+ <td class="default">
851
+
852
+ </td>
853
+
630
854
 
631
- <td class="description last"><p>輸入時區時間函數,傳入時間字串回傳dayjs時間物件(可用src/ott.mjs或自行以dayjs包裝)</p></td>
855
+ <td class="description last"><p>輸入K線陣列,各元素需含time、High、Low欄位</p></td>
632
856
  </tr>
633
857
 
634
858
 
@@ -649,10 +873,132 @@ console.log(orders[0])
649
873
  </td>
650
874
 
651
875
 
876
+ <td class="attributes">
877
+
878
+
879
+
880
+
881
+
882
+ </td>
883
+
652
884
 
653
885
 
886
+ <td class="default">
887
+
888
+ </td>
889
+
654
890
 
655
- <td class="description last"><p>輸入已結算訂單陣列,各元素需含modeResult、timeStart、timeEnd、rProfitOrLoss欄位</p></td>
891
+ <td class="description last"><p>輸入下單陣列,各元素需含mode('long'或'short')、timeStart、priceStart、uTrade、priceTakeProfit、priceStopLoss、uFee欄位</p></td>
892
+ </tr>
893
+
894
+
895
+
896
+ <tr>
897
+
898
+ <td class="name"><code>opt</code></td>
899
+
900
+
901
+ <td class="type">
902
+
903
+
904
+ <span class="param-type">Object</span>
905
+
906
+
907
+
908
+
909
+ </td>
910
+
911
+
912
+ <td class="attributes">
913
+
914
+ &lt;optional><br>
915
+
916
+
917
+
918
+
919
+
920
+ </td>
921
+
922
+
923
+
924
+ <td class="default">
925
+
926
+ <code>{}</code>
927
+
928
+ </td>
929
+
930
+
931
+ <td class="description last"><p>輸入設定物件,預設{}</p>
932
+ <h6>Properties</h6>
933
+
934
+
935
+ <table class="params">
936
+ <thead>
937
+ <tr>
938
+
939
+ <th>Name</th>
940
+
941
+
942
+ <th>Type</th>
943
+
944
+
945
+ <th>Attributes</th>
946
+
947
+
948
+
949
+ <th>Default</th>
950
+
951
+
952
+ <th class="last">Description</th>
953
+ </tr>
954
+ </thead>
955
+
956
+ <tbody>
957
+
958
+
959
+ <tr>
960
+
961
+ <td class="name"><code>uIni</code></td>
962
+
963
+
964
+ <td class="type">
965
+
966
+
967
+ <span class="param-type">Number</span>
968
+
969
+
970
+
971
+
972
+ </td>
973
+
974
+
975
+ <td class="attributes">
976
+
977
+ &lt;optional><br>
978
+
979
+
980
+
981
+
982
+
983
+ </td>
984
+
985
+
986
+
987
+ <td class="default">
988
+
989
+ <code>1000</code>
990
+
991
+ </td>
992
+
993
+
994
+ <td class="description last"><p>輸入初始資金數字,預設1000</p></td>
995
+ </tr>
996
+
997
+
998
+ </tbody>
999
+ </table>
1000
+
1001
+ </td>
656
1002
  </tr>
657
1003
 
658
1004
 
@@ -678,7 +1024,7 @@ console.log(orders[0])
678
1024
 
679
1025
 
680
1026
  <div class="param-desc">
681
- <p>回傳附加dayHold與rProfitOrLossDay之訂單陣列</p>
1027
+ <p>回傳Promise,resolve為結算後訂單陣列</p>
682
1028
  </div>
683
1029
 
684
1030
 
@@ -689,7 +1035,7 @@ console.log(orders[0])
689
1035
  </dt>
690
1036
  <dd>
691
1037
 
692
- <span class="param-type">Array</span>
1038
+ <span class="param-type">Promise</span>
693
1039
 
694
1040
 
695
1041
 
@@ -705,7 +1051,7 @@ console.log(orders[0])
705
1051
 
706
1052
 
707
1053
 
708
- <h4 class="name" id="calcOrdersSummary"><span class="type-signature"></span>calcOrdersSummary<span class="signature">(ott, uIni, ordersAll, timeOhlcStart, timeOhlcEnd)</span><span class="type-signature"> &rarr; {Object}</span></h4>
1054
+ <h4 class="name" id="calcOrdersRatio"><span class="type-signature"></span>calcOrdersRatio<span class="signature">(ott, orders)</span><span class="type-signature"> &rarr; {Array}</span></h4>
709
1055
 
710
1056
 
711
1057
 
@@ -715,17 +1061,16 @@ console.log(orders[0])
715
1061
  <dl class="details">
716
1062
 
717
1063
  <dt class="tag-description">Description:</dt>
718
- <dd class="tag-description"><ul class="dummy"><li><p>統計全部訂單之回測摘要</p>
719
- <p>統計交易次數、勝率、最大回撤、最大持倉、夏普值、最終權益與各盈虧比例等欄位
720
- 訂單需先經calcOrders結算(含uEquity)與calcOrdersRatio計算(含dayHold與rProfitOrLossDay,夏普值計算所需)
721
- uIni非正數或timeOhlcStart、timeOhlcEnd非有效字串時throw</p>
1064
+ <dd class="tag-description"><ul class="dummy"><li><p>計算各已平倉訂單之持倉天數與等效日盈虧比例</p>
1065
+ <p>dayHold以timeStart與timeEnd之日期差+1計算,rProfitOrLossDay為(1+rProfitOrLoss)^(1/dayHold)-1
1066
+ modeResult非有效字串(未平倉)之訂單不計算</p>
722
1067
  <p>Unit Test: <a href="https://github.com/yuda-lyu/w-trade-backtest/blob/master/test/unit-WTradeBacktest.test.mjs">Github</a></p></li></ul></dd>
723
1068
 
724
1069
 
725
1070
 
726
1071
  <dt class="tag-source">Source:</dt>
727
1072
  <dd class="tag-source"><ul class="dummy"><li>
728
- <a href="calcOrdersSummary.mjs.html">calcOrdersSummary.mjs</a>, <a href="calcOrdersSummary.mjs.html#line76">line 76</a>
1073
+ <a href="calcOrdersRatio.mjs.html">calcOrdersRatio.mjs</a>, <a href="calcOrdersRatio.mjs.html#line35">line 35</a>
729
1074
  </li></ul></dd>
730
1075
 
731
1076
 
@@ -772,33 +1117,238 @@ uIni非正數或timeOhlcStart、timeOhlcEnd非有效字串時throw</p>
772
1117
 
773
1118
  <h5 class="h5-examples">Example</h5>
774
1119
 
775
- <pre class="prettyprint"><code>let arrOhlc = [
776
- { time: '2020-01-01T00:00:00', Open: 100, High: 101, Low: 99, Close: 100 },
777
- { time: '2020-01-01T04:00:00', Open: 100, High: 106, Low: 100, Close: 105 },
778
- { time: '2020-01-01T08:00:00', Open: 105, High: 107, Low: 102, Close: 103 },
779
- { time: '2020-01-01T12:00:00', Open: 103, High: 104, Low: 94, Close: 95 },
780
- { time: '2020-01-01T16:00:00', Open: 95, High: 98, Low: 92, Close: 93 },
781
- { time: '2020-01-01T20:00:00', Open: 93, High: 99, Low: 95, Close: 97 },
782
- ]
1120
+ <pre class="prettyprint"><code>let orders = calcOrdersRatio(ott, [{
1121
+ modeResult: 'profit',
1122
+ timeStart: '2020-01-01T20:00:00',
1123
+ timeEnd: '2020-01-03T04:00:00',
1124
+ rProfitOrLoss: 0.331,
1125
+ }])
1126
+ console.log(orders[0])
1127
+ // => {
1128
+ // modeResult: 'profit',
1129
+ // timeStart: '2020-01-01T20:00:00',
1130
+ // timeEnd: '2020-01-03T04:00:00',
1131
+ // rProfitOrLoss: 0.331,
1132
+ // dayHold: 3,
1133
+ // rProfitOrLossDay: 0.10000000000000009
1134
+ // }</code></pre>
783
1135
 
784
- //ordersSubmit, 4張下單: 前3張分別於後續K棒觸發止盈或止損, 第4張未觸發(未平倉)
785
- let kpDef = { uTrade: 100, timeEnd: '', priceEnd: '', modeResult: '', uFee: 0.05 }
786
- let ordersSubmit = [
787
- { mode: 'long', timeStart: '2020-01-01T00:00:00', priceStart: 100, priceTakeProfit: 105, priceStopLoss: 97, ...kpDef },
788
- { mode: 'long', timeStart: '2020-01-01T04:00:00', priceStart: 105, priceTakeProfit: 110.25, priceStopLoss: 101.85, ...kpDef },
789
- { mode: 'short', timeStart: '2020-01-01T08:00:00', priceStart: 103, priceTakeProfit: 97.85, priceStopLoss: 106.09, ...kpDef },
790
- { mode: 'long', timeStart: '2020-01-01T16:00:00', priceStart: 93, priceTakeProfit: 105, priceStopLoss: 85, ...kpDef },
791
- ]
792
1136
 
793
- let orders = await calcOrders(arrOhlc, ordersSubmit, { uIni: 1000 })
794
- orders = calcOrdersRatio(ott, orders)
795
- let summary = calcOrdersSummary(ott, 1000, orders, '2020-01-01T00:00:00', '2020-01-01T20:00:00')
796
- console.log(summary)
797
- // => {
798
- // btDays: 0,
799
- // btYears: '0.0',
800
- // numTrade: 4,
801
- // numTradeFin: 3,
1137
+
1138
+
1139
+ <h5 class="h5-parameters">Parameters:</h5>
1140
+
1141
+
1142
+ <table class="params">
1143
+ <thead>
1144
+ <tr>
1145
+
1146
+ <th>Name</th>
1147
+
1148
+
1149
+ <th>Type</th>
1150
+
1151
+
1152
+
1153
+
1154
+
1155
+ <th class="last">Description</th>
1156
+ </tr>
1157
+ </thead>
1158
+
1159
+ <tbody>
1160
+
1161
+
1162
+ <tr>
1163
+
1164
+ <td class="name"><code>ott</code></td>
1165
+
1166
+
1167
+ <td class="type">
1168
+
1169
+
1170
+ <span class="param-type">function</span>
1171
+
1172
+
1173
+
1174
+
1175
+ </td>
1176
+
1177
+
1178
+
1179
+
1180
+
1181
+ <td class="description last"><p>輸入時區時間函數,傳入時間字串回傳dayjs時間物件(可用src/ott.mjs或自行以dayjs包裝)</p></td>
1182
+ </tr>
1183
+
1184
+
1185
+
1186
+ <tr>
1187
+
1188
+ <td class="name"><code>orders</code></td>
1189
+
1190
+
1191
+ <td class="type">
1192
+
1193
+
1194
+ <span class="param-type">Array</span>
1195
+
1196
+
1197
+
1198
+
1199
+ </td>
1200
+
1201
+
1202
+
1203
+
1204
+
1205
+ <td class="description last"><p>輸入已結算訂單陣列,各元素需含modeResult、timeStart、timeEnd、rProfitOrLoss欄位</p></td>
1206
+ </tr>
1207
+
1208
+
1209
+ </tbody>
1210
+ </table>
1211
+
1212
+
1213
+
1214
+
1215
+
1216
+
1217
+
1218
+
1219
+
1220
+
1221
+
1222
+
1223
+
1224
+
1225
+
1226
+
1227
+ <h5 class="h5-returns">Returns:</h5>
1228
+
1229
+
1230
+ <div class="param-desc">
1231
+ <p>回傳附加dayHold與rProfitOrLossDay之訂單陣列</p>
1232
+ </div>
1233
+
1234
+
1235
+
1236
+ <dl class="param-type">
1237
+ <dt>
1238
+ Type
1239
+ </dt>
1240
+ <dd>
1241
+
1242
+ <span class="param-type">Array</span>
1243
+
1244
+
1245
+
1246
+ </dd>
1247
+ </dl>
1248
+
1249
+
1250
+
1251
+
1252
+
1253
+
1254
+
1255
+
1256
+
1257
+
1258
+ <h4 class="name" id="calcOrdersSummary"><span class="type-signature"></span>calcOrdersSummary<span class="signature">(ott, uIni, ordersAll, timeOhlcStart, timeOhlcEnd)</span><span class="type-signature"> &rarr; {Object}</span></h4>
1259
+
1260
+
1261
+
1262
+
1263
+
1264
+
1265
+ <dl class="details">
1266
+
1267
+ <dt class="tag-description">Description:</dt>
1268
+ <dd class="tag-description"><ul class="dummy"><li><p>統計全部訂單之回測摘要</p>
1269
+ <p>統計交易次數、勝率、最大回撤、最大持倉、夏普值、最終權益與各盈虧比例等欄位
1270
+ 訂單需先經calcOrders結算(含uEquity)與calcOrdersRatio計算(含dayHold與rProfitOrLossDay,夏普值計算所需)
1271
+ uIni非正數或timeOhlcStart、timeOhlcEnd非有效字串時throw</p>
1272
+ <p>Unit Test: <a href="https://github.com/yuda-lyu/w-trade-backtest/blob/master/test/unit-WTradeBacktest.test.mjs">Github</a></p></li></ul></dd>
1273
+
1274
+
1275
+
1276
+ <dt class="tag-source">Source:</dt>
1277
+ <dd class="tag-source"><ul class="dummy"><li>
1278
+ <a href="calcOrdersSummary.mjs.html">calcOrdersSummary.mjs</a>, <a href="calcOrdersSummary.mjs.html#line76">line 76</a>
1279
+ </li></ul></dd>
1280
+
1281
+
1282
+
1283
+
1284
+
1285
+
1286
+
1287
+
1288
+
1289
+
1290
+
1291
+
1292
+
1293
+
1294
+
1295
+
1296
+
1297
+
1298
+
1299
+
1300
+
1301
+
1302
+
1303
+
1304
+
1305
+
1306
+
1307
+
1308
+
1309
+
1310
+
1311
+ </dl>
1312
+
1313
+
1314
+
1315
+
1316
+
1317
+
1318
+
1319
+
1320
+
1321
+
1322
+
1323
+ <h5 class="h5-examples">Example</h5>
1324
+
1325
+ <pre class="prettyprint"><code>let arrOhlc = [
1326
+ { time: '2020-01-01T00:00:00', Open: 100, High: 101, Low: 99, Close: 100 },
1327
+ { time: '2020-01-01T04:00:00', Open: 100, High: 106, Low: 100, Close: 105 },
1328
+ { time: '2020-01-01T08:00:00', Open: 105, High: 107, Low: 102, Close: 103 },
1329
+ { time: '2020-01-01T12:00:00', Open: 103, High: 104, Low: 94, Close: 95 },
1330
+ { time: '2020-01-01T16:00:00', Open: 95, High: 98, Low: 92, Close: 93 },
1331
+ { time: '2020-01-01T20:00:00', Open: 93, High: 99, Low: 95, Close: 97 },
1332
+ ]
1333
+
1334
+ //ordersSubmit, 4張下單: 前3張分別於後續K棒觸發止盈或止損, 第4張未觸發(未平倉)
1335
+ let kpDef = { uTrade: 100, timeEnd: '', priceEnd: '', modeResult: '', uFee: 0.05 }
1336
+ let ordersSubmit = [
1337
+ { mode: 'long', timeStart: '2020-01-01T00:00:00', priceStart: 100, priceTakeProfit: 105, priceStopLoss: 97, ...kpDef },
1338
+ { mode: 'long', timeStart: '2020-01-01T04:00:00', priceStart: 105, priceTakeProfit: 110.25, priceStopLoss: 101.85, ...kpDef },
1339
+ { mode: 'short', timeStart: '2020-01-01T08:00:00', priceStart: 103, priceTakeProfit: 97.85, priceStopLoss: 106.09, ...kpDef },
1340
+ { mode: 'long', timeStart: '2020-01-01T16:00:00', priceStart: 93, priceTakeProfit: 105, priceStopLoss: 85, ...kpDef },
1341
+ ]
1342
+
1343
+ let orders = await calcOrders(arrOhlc, ordersSubmit, { uIni: 1000 })
1344
+ orders = calcOrdersRatio(ott, orders)
1345
+ let summary = calcOrdersSummary(ott, 1000, orders, '2020-01-01T00:00:00', '2020-01-01T20:00:00')
1346
+ console.log(summary)
1347
+ // => {
1348
+ // btDays: 0,
1349
+ // btYears: '0.0',
1350
+ // numTrade: 4,
1351
+ // numTradeFin: 3,
802
1352
  // numTradeUnsettled: 1,
803
1353
  // uTradeAllMax: 200,
804
1354
  // rTradeAllMax: '20.00%',
@@ -2584,7 +3134,7 @@ console.log(fs.readdirSync('./result'))
2584
3134
 
2585
3135
 
2586
3136
 
2587
- <h4 class="name" id="genReport"><span class="type-signature type-signature-async">(async) </span>genReport<span class="signature">(ott, fpOrders, opt<span class="signature-attributes">opt</span>)</span><span class="type-signature"> &rarr; {Promise}</span></h4>
3137
+ <h4 class="name" id="genKLinesTpSl"><span class="type-signature"></span>genKLinesTpSl<span class="signature">(arrOhlc, opt<span class="signature-attributes">opt</span>)</span><span class="type-signature"> &rarr; {Object}</span></h4>
2588
3138
 
2589
3139
 
2590
3140
 
@@ -2594,17 +3144,17 @@ console.log(fs.readdirSync('./result'))
2594
3144
  <dl class="details">
2595
3145
 
2596
3146
  <dt class="tag-description">Description:</dt>
2597
- <dd class="tag-description"><ul class="dummy"><li><p>由orders.json產製績效html報表</p>
2598
- <p>讀取orders.json(已結算訂單陣列)後,經calcSummary統計摘要,再以genReportCore產出html報表
2599
- 訂單須為已結算形(含uProfitOrLoss、uEquity等欄位),未結算單(timeEnd為空)仍可計算,計入summary.numTradeUnsettled
2600
- fpOrders非有效字串或非檔案、內容非有效陣列時throw</p>
3147
+ <dd class="tag-description"><ul class="dummy"><li><p>計算各K線進場後之止盈止損先觸結果</p>
3148
+ <p>以各根K線收盤價為進場價,往後逐根K線掃描first-touch,long以Low&lt;=進場價*(1-sl)判止損、High&gt;=進場價*(1+tp)判止盈
3149
+ short以High&gt;=進場價*(1+sl)判止損、Low&lt;=進場價*(1-tp)判止盈,同根同時觸發時皆先判止損
3150
+ 末根K線與掃描至序列末仍未觸發者視為未結,win為-1且pnl與hold為NaN</p>
2601
3151
  <p>Unit Test: <a href="https://github.com/yuda-lyu/w-trade-backtest/blob/master/test/unit-WTradeBacktest.test.mjs">Github</a></p></li></ul></dd>
2602
3152
 
2603
3153
 
2604
3154
 
2605
3155
  <dt class="tag-source">Source:</dt>
2606
3156
  <dd class="tag-source"><ul class="dummy"><li>
2607
- <a href="genReport.mjs.html">genReport.mjs</a>, <a href="genReport.mjs.html#line61">line 61</a>
3157
+ <a href="genKLinesTpSl.mjs.html">genKLinesTpSl.mjs</a>, <a href="genKLinesTpSl.mjs.html#line36">line 36</a>
2608
3158
  </li></ul></dd>
2609
3159
 
2610
3160
 
@@ -2651,7 +3201,22 @@ fpOrders非有效字串或非檔案、內容非有效陣列時throw</p>
2651
3201
 
2652
3202
  <h5 class="h5-examples">Example</h5>
2653
3203
 
2654
- <pre class="prettyprint"><code>import fs from 'fs'
2655
3204
  mode: 'long',
2656
3205
  timeStart: '2020-01-01T00:00:00',
2657
3206
  priceStart: 100,
2658
3207
  uTrade: 100,
2659
3208
  priceTakeProfit: 105,
2660
3209
  priceStopLoss: 97,
2661
3210
  timeEnd: '2020-01-01T04:00:00',
2662
3211
  priceEnd: 105,
2663
3212
  modeResult: 'profit',
2664
3213
  uFee: 0.05,
2665
3214
  uProfitOrLoss: 4.9,
2666
3215
  rProfitOrLoss: 0.049,
2667
3216
  uCumuProfitOrLoss: 4.9,
2668
3217
  uEquity: 1004.9,
3218
+ <pre class="prettyprint"><code>let arrOhlc = [
3219
+ { time: '2020-01-01T00:00:00', Open: 100, High: 101, Low: 99, Close: 100 },
3220
+ { time: '2020-01-01T04:00:00', Open: 100, High: 106, Low: 100, Close: 105 },
3221
+ { time: '2020-01-01T08:00:00', Open: 105, High: 107, Low: 102, Close: 103 },
3222
+ { time: '2020-01-01T12:00:00', Open: 103, High: 104, Low: 94, Close: 95 },
3223
+ { time: '2020-01-01T16:00:00', Open: 95, High: 98, Low: 92, Close: 93 },
3224
+ { time: '2020-01-01T20:00:00', Open: 93, High: 99, Low: 95, Close: 97 },
3225
+ ]
3226
+
3227
+ let r = genKLinesTpSl(arrOhlc, { tp: 0.05, sl: 0.05, mode: 'long' })
3228
+ console.log(Array.from(r.win))
3229
+ // => [ 1, 0, 0, -1, 1, -1 ]
3230
+ console.log(Array.from(r.hold))
3231
+ // => [ 1, 2, 1, NaN, 1, NaN ]
3232
+ console.log(Array.from(r.pnl))
3233
+ // => [ 0.05, -0.05, -0.05, NaN, 0.05, NaN ]</code></pre>
2669
3234
 
2670
3235
 
2671
3236
 
@@ -2685,13 +3250,13 @@ fpOrders非有效字串或非檔案、內容非有效陣列時throw</p>
2685
3250
 
2686
3251
  <tr>
2687
3252
 
2688
- <td class="name"><code>ott</code></td>
3253
+ <td class="name"><code>arrOhlc</code></td>
2689
3254
 
2690
3255
 
2691
3256
  <td class="type">
2692
3257
 
2693
3258
 
2694
- <span class="param-type">function</span>
3259
+ <span class="param-type">Array</span>
2695
3260
 
2696
3261
 
2697
3262
 
@@ -2714,20 +3279,20 @@ fpOrders非有效字串或非檔案、內容非有效陣列時throw</p>
2714
3279
  </td>
2715
3280
 
2716
3281
 
2717
- <td class="description last"><p>輸入時區時間函數,傳入時間字串回傳dayjs時間物件(可用src/ott.mjs或自行以dayjs包裝)</p></td>
3282
+ <td class="description last"><p>輸入K線陣列,各元素需含time(秒時間字串)、Close、High、Low欄位,且依時間由小至大排序</p></td>
2718
3283
  </tr>
2719
3284
 
2720
3285
 
2721
3286
 
2722
3287
  <tr>
2723
3288
 
2724
- <td class="name"><code>fpOrders</code></td>
3289
+ <td class="name"><code>opt</code></td>
2725
3290
 
2726
3291
 
2727
3292
  <td class="type">
2728
3293
 
2729
3294
 
2730
- <span class="param-type">String</span>
3295
+ <span class="param-type">Object</span>
2731
3296
 
2732
3297
 
2733
3298
 
@@ -2737,6 +3302,8 @@ fpOrders非有效字串或非檔案、內容非有效陣列時throw</p>
2737
3302
 
2738
3303
  <td class="attributes">
2739
3304
 
3305
+ &lt;optional><br>
3306
+
2740
3307
 
2741
3308
 
2742
3309
 
@@ -2747,23 +3314,48 @@ fpOrders非有效字串或非檔案、內容非有效陣列時throw</p>
2747
3314
 
2748
3315
  <td class="default">
2749
3316
 
3317
+ <code>{}</code>
3318
+
2750
3319
  </td>
2751
3320
 
2752
3321
 
2753
- <td class="description last"><p>輸入orders.json檔案路徑字串</p></td>
2754
- </tr>
3322
+ <td class="description last"><p>輸入設定物件,預設{}</p>
3323
+ <h6>Properties</h6>
3324
+
2755
3325
 
2756
-
3326
+ <table class="params">
3327
+ <thead>
3328
+ <tr>
3329
+
3330
+ <th>Name</th>
3331
+
3332
+
3333
+ <th>Type</th>
3334
+
3335
+
3336
+ <th>Attributes</th>
3337
+
3338
+
3339
+
3340
+ <th>Default</th>
3341
+
3342
+
3343
+ <th class="last">Description</th>
3344
+ </tr>
3345
+ </thead>
3346
+
3347
+ <tbody>
3348
+
2757
3349
 
2758
3350
  <tr>
2759
3351
 
2760
- <td class="name"><code>opt</code></td>
3352
+ <td class="name"><code>tp</code></td>
2761
3353
 
2762
3354
 
2763
3355
  <td class="type">
2764
3356
 
2765
3357
 
2766
- <span class="param-type">Object</span>
3358
+ <span class="param-type">Number</span>
2767
3359
 
2768
3360
 
2769
3361
 
@@ -2773,7 +3365,41 @@ fpOrders非有效字串或非檔案、內容非有效陣列時throw</p>
2773
3365
 
2774
3366
  <td class="attributes">
2775
3367
 
2776
- &lt;optional><br>
3368
+
3369
+
3370
+
3371
+
3372
+ </td>
3373
+
3374
+
3375
+
3376
+ <td class="default">
3377
+
3378
+ </td>
3379
+
3380
+
3381
+ <td class="description last"><p>輸入止盈比例正數,如0.05代表5%</p></td>
3382
+ </tr>
3383
+
3384
+
3385
+
3386
+ <tr>
3387
+
3388
+ <td class="name"><code>sl</code></td>
3389
+
3390
+
3391
+ <td class="type">
3392
+
3393
+
3394
+ <span class="param-type">Number</span>
3395
+
3396
+
3397
+
3398
+
3399
+ </td>
3400
+
3401
+
3402
+ <td class="attributes">
2777
3403
 
2778
3404
 
2779
3405
 
@@ -2785,14 +3411,183 @@ fpOrders非有效字串或非檔案、內容非有效陣列時throw</p>
2785
3411
 
2786
3412
  <td class="default">
2787
3413
 
2788
- <code>{}</code>
3414
+ </td>
3415
+
3416
+
3417
+ <td class="description last"><p>輸入止損比例正數,如0.05代表5%</p></td>
3418
+ </tr>
3419
+
3420
+
3421
+
3422
+ <tr>
3423
+
3424
+ <td class="name"><code>mode</code></td>
3425
+
3426
+
3427
+ <td class="type">
3428
+
3429
+
3430
+ <span class="param-type">String</span>
3431
+
3432
+
3433
+
3434
+
3435
+ </td>
3436
+
3437
+
3438
+ <td class="attributes">
3439
+
3440
+ &lt;optional><br>
3441
+
3442
+
3443
+
3444
+
2789
3445
 
2790
3446
  </td>
2791
3447
 
2792
3448
 
2793
- <td class="description last"><p>輸入設定物件,預設{}</p>
2794
- <h6>Properties</h6>
3449
+
3450
+ <td class="default">
2795
3451
 
3452
+ <code>'long'</code>
3453
+
3454
+ </td>
3455
+
3456
+
3457
+ <td class="description last"><p>輸入交易方向字串,可為'long'或'short',預設'long'</p></td>
3458
+ </tr>
3459
+
3460
+
3461
+ </tbody>
3462
+ </table>
3463
+
3464
+ </td>
3465
+ </tr>
3466
+
3467
+
3468
+ </tbody>
3469
+ </table>
3470
+
3471
+
3472
+
3473
+
3474
+
3475
+
3476
+
3477
+
3478
+
3479
+
3480
+
3481
+
3482
+
3483
+
3484
+
3485
+
3486
+ <h5 class="h5-returns">Returns:</h5>
3487
+
3488
+
3489
+ <div class="param-desc">
3490
+ <p>回傳物件,內含time(時間字串陣列)、pnl(Float64Array,止盈為tp、止損為-sl、未結為NaN)、win(Int8Array,1為止盈先觸、0為止損先觸、-1為未結)、hold(Float64Array,出場K線與進場K線之位移根數,未結為NaN)欄位,各陣列長度同arrOhlc且index對應</p>
3491
+ </div>
3492
+
3493
+
3494
+
3495
+ <dl class="param-type">
3496
+ <dt>
3497
+ Type
3498
+ </dt>
3499
+ <dd>
3500
+
3501
+ <span class="param-type">Object</span>
3502
+
3503
+
3504
+
3505
+ </dd>
3506
+ </dl>
3507
+
3508
+
3509
+
3510
+
3511
+
3512
+
3513
+
3514
+
3515
+
3516
+
3517
+ <h4 class="name" id="genReport"><span class="type-signature type-signature-async">(async) </span>genReport<span class="signature">(ott, fpOrders, opt<span class="signature-attributes">opt</span>)</span><span class="type-signature"> &rarr; {Promise}</span></h4>
3518
+
3519
+
3520
+
3521
+
3522
+
3523
+
3524
+ <dl class="details">
3525
+
3526
+ <dt class="tag-description">Description:</dt>
3527
+ <dd class="tag-description"><ul class="dummy"><li><p>由orders.json產製績效html報表</p>
3528
+ <p>讀取orders.json(已結算訂單陣列)後,經calcSummary統計摘要,再以genReportCore產出html報表
3529
+ 訂單須為已結算形(含uProfitOrLoss、uEquity等欄位),未結算單(timeEnd為空)仍可計算,計入summary.numTradeUnsettled
3530
+ fpOrders非有效字串或非檔案、內容非有效陣列時throw</p>
3531
+ <p>Unit Test: <a href="https://github.com/yuda-lyu/w-trade-backtest/blob/master/test/unit-WTradeBacktest.test.mjs">Github</a></p></li></ul></dd>
3532
+
3533
+
3534
+
3535
+ <dt class="tag-source">Source:</dt>
3536
+ <dd class="tag-source"><ul class="dummy"><li>
3537
+ <a href="genReport.mjs.html">genReport.mjs</a>, <a href="genReport.mjs.html#line61">line 61</a>
3538
+ </li></ul></dd>
3539
+
3540
+
3541
+
3542
+
3543
+
3544
+
3545
+
3546
+
3547
+
3548
+
3549
+
3550
+
3551
+
3552
+
3553
+
3554
+
3555
+
3556
+
3557
+
3558
+
3559
+
3560
+
3561
+
3562
+
3563
+
3564
+
3565
+
3566
+
3567
+
3568
+
3569
+
3570
+ </dl>
3571
+
3572
+
3573
+
3574
+
3575
+
3576
+
3577
+
3578
+
3579
+
3580
+
3581
+
3582
+ <h5 class="h5-examples">Example</h5>
3583
+
3584
+ <pre class="prettyprint"><code>import fs from 'fs'
2796
3585
  mode: 'long',
2797
3586
  timeStart: '2020-01-01T00:00:00',
2798
3587
  priceStart: 100,
2799
3588
  uTrade: 100,
2800
3589
  priceTakeProfit: 105,
2801
3590
  priceStopLoss: 97,
2802
3591
  timeEnd: '2020-01-01T04:00:00',
2803
3592
  priceEnd: 105,
2804
3593
  modeResult: 'profit',
2805
3594
  uFee: 0.05,
2806
3595
  uProfitOrLoss: 4.9,
2807
3596
  rProfitOrLoss: 0.049,
2808
3597
  uCumuProfitOrLoss: 4.9,
2809
3598
  uEquity: 1004.9,
3599
+
3600
+
3601
+
3602
+
3603
+ <h5 class="h5-parameters">Parameters:</h5>
3604
+
2810
3605
 
2811
3606
  <table class="params">
2812
3607
  <thead>
@@ -2820,13 +3615,13 @@ fpOrders非有效字串或非檔案、內容非有效陣列時throw</p>
2820
3615
 
2821
3616
  <tr>
2822
3617
 
2823
- <td class="name"><code>fpOut</code></td>
3618
+ <td class="name"><code>ott</code></td>
2824
3619
 
2825
3620
 
2826
3621
  <td class="type">
2827
3622
 
2828
3623
 
2829
- <span class="param-type">String</span>
3624
+ <span class="param-type">function</span>
2830
3625
 
2831
3626
 
2832
3627
 
@@ -2836,8 +3631,6 @@ fpOrders非有效字串或非檔案、內容非有效陣列時throw</p>
2836
3631
 
2837
3632
  <td class="attributes">
2838
3633
 
2839
- &lt;optional><br>
2840
-
2841
3634
 
2842
3635
 
2843
3636
 
@@ -2848,19 +3641,17 @@ fpOrders非有效字串或非檔案、內容非有效陣列時throw</p>
2848
3641
 
2849
3642
  <td class="default">
2850
3643
 
2851
- <code>''</code>
2852
-
2853
3644
  </td>
2854
3645
 
2855
3646
 
2856
- <td class="description last"><p>輸入輸出html檔案路徑字串,預設為與orders.json同資料夾之report.html</p></td>
3647
+ <td class="description last"><p>輸入時區時間函數,傳入時間字串回傳dayjs時間物件(可用src/ott.mjs或自行以dayjs包裝)</p></td>
2857
3648
  </tr>
2858
3649
 
2859
3650
 
2860
3651
 
2861
3652
  <tr>
2862
3653
 
2863
- <td class="name"><code>name</code></td>
3654
+ <td class="name"><code>fpOrders</code></td>
2864
3655
 
2865
3656
 
2866
3657
  <td class="type">
@@ -2876,37 +3667,906 @@ fpOrders非有效字串或非檔案、內容非有效陣列時throw</p>
2876
3667
 
2877
3668
  <td class="attributes">
2878
3669
 
2879
- &lt;optional><br>
3670
+
3671
+
3672
+
2880
3673
 
3674
+ </td>
3675
+
3676
+
3677
+
3678
+ <td class="default">
3679
+
3680
+ </td>
3681
+
3682
+
3683
+ <td class="description last"><p>輸入orders.json檔案路徑字串</p></td>
3684
+ </tr>
3685
+
3686
+
3687
+
3688
+ <tr>
3689
+
3690
+ <td class="name"><code>opt</code></td>
3691
+
3692
+
3693
+ <td class="type">
3694
+
3695
+
3696
+ <span class="param-type">Object</span>
3697
+
3698
+
3699
+
3700
+
3701
+ </td>
3702
+
3703
+
3704
+ <td class="attributes">
3705
+
3706
+ &lt;optional><br>
3707
+
3708
+
3709
+
3710
+
3711
+
3712
+ </td>
3713
+
3714
+
3715
+
3716
+ <td class="default">
3717
+
3718
+ <code>{}</code>
3719
+
3720
+ </td>
3721
+
3722
+
3723
+ <td class="description last"><p>輸入設定物件,預設{}</p>
3724
+ <h6>Properties</h6>
3725
+
3726
+
3727
+ <table class="params">
3728
+ <thead>
3729
+ <tr>
3730
+
3731
+ <th>Name</th>
3732
+
3733
+
3734
+ <th>Type</th>
3735
+
3736
+
3737
+ <th>Attributes</th>
3738
+
3739
+
3740
+
3741
+ <th>Default</th>
3742
+
3743
+
3744
+ <th class="last">Description</th>
3745
+ </tr>
3746
+ </thead>
3747
+
3748
+ <tbody>
3749
+
3750
+
3751
+ <tr>
3752
+
3753
+ <td class="name"><code>fpOut</code></td>
3754
+
3755
+
3756
+ <td class="type">
3757
+
3758
+
3759
+ <span class="param-type">String</span>
3760
+
3761
+
3762
+
3763
+
3764
+ </td>
3765
+
3766
+
3767
+ <td class="attributes">
3768
+
3769
+ &lt;optional><br>
3770
+
3771
+
3772
+
3773
+
3774
+
3775
+ </td>
3776
+
3777
+
3778
+
3779
+ <td class="default">
3780
+
3781
+ <code>''</code>
3782
+
3783
+ </td>
3784
+
3785
+
3786
+ <td class="description last"><p>輸入輸出html檔案路徑字串,預設為與orders.json同資料夾之report.html</p></td>
3787
+ </tr>
3788
+
3789
+
3790
+
3791
+ <tr>
3792
+
3793
+ <td class="name"><code>name</code></td>
3794
+
3795
+
3796
+ <td class="type">
3797
+
3798
+
3799
+ <span class="param-type">String</span>
3800
+
3801
+
3802
+
3803
+
3804
+ </td>
3805
+
3806
+
3807
+ <td class="attributes">
3808
+
3809
+ &lt;optional><br>
3810
+
3811
+
3812
+
3813
+
3814
+
3815
+ </td>
3816
+
3817
+
3818
+
3819
+ <td class="default">
3820
+
3821
+ <code>''</code>
3822
+
3823
+ </td>
3824
+
3825
+
3826
+ <td class="description last"><p>輸入報表標題字串,預設為orders.json所在資料夾名</p></td>
3827
+ </tr>
3828
+
3829
+
3830
+
3831
+ <tr>
3832
+
3833
+ <td class="name"><code>uIni</code></td>
3834
+
3835
+
3836
+ <td class="type">
3837
+
3838
+
3839
+ <span class="param-type">Number</span>
3840
+
3841
+
3842
+
3843
+
3844
+ </td>
3845
+
3846
+
3847
+ <td class="attributes">
3848
+
3849
+ &lt;optional><br>
3850
+
3851
+
3852
+
3853
+
3854
+
3855
+ </td>
3856
+
3857
+
3858
+
3859
+ <td class="default">
3860
+
3861
+ <code>null</code>
3862
+
3863
+ </td>
3864
+
3865
+
3866
+ <td class="description last"><p>輸入初始資金數值,預設由首筆已結算單推回(uEquity - uCumuProfitOrLoss),推不出則為1000</p></td>
3867
+ </tr>
3868
+
3869
+
3870
+
3871
+ <tr>
3872
+
3873
+ <td class="name"><code>timeOhlcStart</code></td>
3874
+
3875
+
3876
+ <td class="type">
3877
+
3878
+
3879
+ <span class="param-type">String</span>
3880
+
3881
+
3882
+
3883
+
3884
+ </td>
3885
+
3886
+
3887
+ <td class="attributes">
3888
+
3889
+ &lt;optional><br>
3890
+
3891
+
3892
+
3893
+
3894
+
3895
+ </td>
3896
+
3897
+
3898
+
3899
+ <td class="default">
3900
+
3901
+ <code>''</code>
3902
+
3903
+ </td>
3904
+
3905
+
3906
+ <td class="description last"><p>輸入摘要統計起始秒時間字串,影響btDays與年化,預設由訂單最早timeStart推得,注意訂單起訖僅為「有單的範圍」,若實際回測窗較寬(頭尾無單)年化會被高估,建議明給</p></td>
3907
+ </tr>
3908
+
3909
+
3910
+
3911
+ <tr>
3912
+
3913
+ <td class="name"><code>timeOhlcEnd</code></td>
3914
+
3915
+
3916
+ <td class="type">
3917
+
3918
+
3919
+ <span class="param-type">String</span>
3920
+
3921
+
3922
+
3923
+
3924
+ </td>
3925
+
3926
+
3927
+ <td class="attributes">
3928
+
3929
+ &lt;optional><br>
3930
+
3931
+
3932
+
3933
+
3934
+
3935
+ </td>
3936
+
3937
+
3938
+
3939
+ <td class="default">
3940
+
3941
+ <code>''</code>
3942
+
3943
+ </td>
3944
+
3945
+
3946
+ <td class="description last"><p>輸入摘要統計結束秒時間字串,預設由訂單最晚timeEnd(未平倉單取timeStart)推得</p></td>
3947
+ </tr>
3948
+
3949
+
3950
+
3951
+ <tr>
3952
+
3953
+ <td class="name"><code>withWriteSummary</code></td>
3954
+
3955
+
3956
+ <td class="type">
3957
+
3958
+
3959
+ <span class="param-type">Boolean</span>
3960
+
3961
+
3962
+
3963
+
3964
+ </td>
3965
+
3966
+
3967
+ <td class="attributes">
3968
+
3969
+ &lt;optional><br>
3970
+
3971
+
3972
+
3973
+
3974
+
3975
+ </td>
3976
+
3977
+
3978
+
3979
+ <td class="default">
3980
+
3981
+ <code>false</code>
3982
+
3983
+ </td>
3984
+
3985
+
3986
+ <td class="description last"><p>輸入是否同時輸出summary.json(與fpOut同資料夾)布林值,預設false</p></td>
3987
+ </tr>
3988
+
3989
+
3990
+ </tbody>
3991
+ </table>
3992
+
3993
+ </td>
3994
+ </tr>
3995
+
3996
+
3997
+ </tbody>
3998
+ </table>
3999
+
4000
+
4001
+
4002
+
4003
+
4004
+
4005
+
4006
+
4007
+
4008
+
4009
+
4010
+
4011
+
4012
+
4013
+
4014
+
4015
+ <h5 class="h5-returns">Returns:</h5>
4016
+
4017
+
4018
+ <div class="param-desc">
4019
+ <p>回傳Promise,resolve為物件,內含orders(訂單陣列)、summary(摘要物件)、fpOut(輸出html路徑)欄位</p>
4020
+ </div>
4021
+
4022
+
4023
+
4024
+ <dl class="param-type">
4025
+ <dt>
4026
+ Type
4027
+ </dt>
4028
+ <dd>
4029
+
4030
+ <span class="param-type">Promise</span>
4031
+
4032
+
4033
+
4034
+ </dd>
4035
+ </dl>
4036
+
4037
+
4038
+
4039
+
4040
+
4041
+
4042
+
4043
+
4044
+
4045
+
4046
+ <h4 class="name" id="genReportCore"><span class="type-signature"></span>genReportCore<span class="signature">(r, fpOut)</span><span class="type-signature"> &rarr; {undefined}</span></h4>
4047
+
4048
+
4049
+
4050
+
4051
+
4052
+
4053
+ <dl class="details">
4054
+
4055
+ <dt class="tag-description">Description:</dt>
4056
+ <dd class="tag-description"><ul class="dummy"><li><p>產出html回測報告</p>
4057
+ <p>讀取與本模組同資料夾之模板資產(tmp.html與render*.js),置換{name}、{orders}、{summary}後寫出html
4058
+ 報告內含權益曲線、訂單表格、時間軸與摘要</p>
4059
+ <p>Unit Test: <a href="https://github.com/yuda-lyu/w-trade-backtest/blob/master/test/unit-WTradeBacktest.test.mjs">Github</a></p></li></ul></dd>
4060
+
4061
+
4062
+
4063
+ <dt class="tag-source">Source:</dt>
4064
+ <dd class="tag-source"><ul class="dummy"><li>
4065
+ <a href="genReportCore.mjs.html">genReportCore.mjs</a>, <a href="genReportCore.mjs.html#line28">line 28</a>
4066
+ </li></ul></dd>
4067
+
4068
+
4069
+
4070
+
4071
+
4072
+
4073
+
4074
+
4075
+
4076
+
4077
+
4078
+
4079
+
4080
+
4081
+
4082
+
4083
+
4084
+
4085
+
4086
+
4087
+
4088
+
4089
+
4090
+
4091
+
4092
+
4093
+
4094
+
4095
+
4096
+
4097
+
4098
+ </dl>
4099
+
4100
+
4101
+
4102
+
4103
+
4104
+
4105
+
4106
+
4107
+
4108
+
4109
+
4110
+ <h5 class="h5-examples">Example</h5>
4111
+
4112
+ <pre class="prettyprint"><code>//rr為runStrategies範例之回傳{orders,summary}
4113
+ genReportCore({ name: '示範策略', orders: rr.orders, summary: rr.summary }, './report.html')
4114
+ // => 於'./report.html'寫出html報告</code></pre>
4115
+
4116
+
4117
+
4118
+
4119
+ <h5 class="h5-parameters">Parameters:</h5>
4120
+
4121
+
4122
+ <table class="params">
4123
+ <thead>
4124
+ <tr>
4125
+
4126
+ <th>Name</th>
4127
+
4128
+
4129
+ <th>Type</th>
4130
+
4131
+
4132
+
4133
+
4134
+
4135
+ <th class="last">Description</th>
4136
+ </tr>
4137
+ </thead>
4138
+
4139
+ <tbody>
4140
+
4141
+
4142
+ <tr>
4143
+
4144
+ <td class="name"><code>r</code></td>
4145
+
4146
+
4147
+ <td class="type">
4148
+
4149
+
4150
+ <span class="param-type">Object</span>
4151
+
4152
+
4153
+
4154
+
4155
+ </td>
4156
+
4157
+
4158
+
4159
+
4160
+
4161
+ <td class="description last"><p>輸入報告物件,需含name(報告名稱字串)、orders(訂單陣列)、summary(摘要物件)欄位</p></td>
4162
+ </tr>
4163
+
4164
+
4165
+
4166
+ <tr>
4167
+
4168
+ <td class="name"><code>fpOut</code></td>
4169
+
4170
+
4171
+ <td class="type">
4172
+
4173
+
4174
+ <span class="param-type">String</span>
4175
+
4176
+
4177
+
4178
+
4179
+ </td>
4180
+
4181
+
4182
+
4183
+
4184
+
4185
+ <td class="description last"><p>輸入輸出html檔案路徑字串</p></td>
4186
+ </tr>
4187
+
4188
+
4189
+ </tbody>
4190
+ </table>
4191
+
4192
+
4193
+
4194
+
4195
+
4196
+
4197
+
4198
+
4199
+
4200
+
4201
+
4202
+
4203
+
4204
+
4205
+
4206
+
4207
+ <h5 class="h5-returns">Returns:</h5>
4208
+
4209
+
4210
+ <div class="param-desc">
4211
+ <p>無回傳,於fpOut寫出html報告</p>
4212
+ </div>
4213
+
4214
+
4215
+
4216
+ <dl class="param-type">
4217
+ <dt>
4218
+ Type
4219
+ </dt>
4220
+ <dd>
4221
+
4222
+ <span class="param-type">undefined</span>
4223
+
4224
+
4225
+
4226
+ </dd>
4227
+ </dl>
4228
+
4229
+
4230
+
4231
+
4232
+
4233
+
4234
+
4235
+
4236
+
4237
+
4238
+ <h4 class="name" id="loadKLinesTpSl"><span class="type-signature"></span>loadKLinesTpSl<span class="signature">(fpJson)</span><span class="type-signature"> &rarr; {Object}</span></h4>
4239
+
4240
+
4241
+
4242
+
4243
+
4244
+
4245
+ <dl class="details">
4246
+
4247
+ <dt class="tag-description">Description:</dt>
4248
+ <dd class="tag-description"><ul class="dummy"><li><p>載入止盈止損先觸結果快取檔並提供訂單重建</p>
4249
+ <p>讀取buildKLinesTpSl產出之快取json,提供ordersFromBars依指定mode與tpsl組合與進場時間陣列重建訂單陣列
4250
+ 重建訂單之盈虧與累計欄位公式逐欄對齊calcOrders,可直接餵入calcOrdersSummary或calcOrdersSummarySimple
4251
+ fpJson非有效字串或非檔案時throw</p>
4252
+ <p>Unit Test: <a href="https://github.com/yuda-lyu/w-trade-backtest/blob/master/test/unit-WTradeBacktest.test.mjs">Github</a></p></li></ul></dd>
4253
+
4254
+
4255
+
4256
+ <dt class="tag-source">Source:</dt>
4257
+ <dd class="tag-source"><ul class="dummy"><li>
4258
+ <a href="loadKLinesTpSl.mjs.html">loadKLinesTpSl.mjs</a>, <a href="loadKLinesTpSl.mjs.html#line36">line 36</a>
4259
+ </li></ul></dd>
4260
+
4261
+
4262
+
4263
+
4264
+
4265
+
4266
+
4267
+
4268
+
4269
+
4270
+
4271
+
4272
+
4273
+
4274
+
4275
+
4276
+
4277
+
4278
+
4279
+
4280
+
4281
+
4282
+
4283
+
4284
+
4285
+
4286
+
4287
+
4288
+
4289
+
4290
+
4291
+ </dl>
4292
+
4293
+
4294
+
4295
+
4296
+
4297
+
4298
+
4299
+
4300
+
4301
+
4302
+
4303
+ <h5 class="h5-examples">Example</h5>
4304
+
4305
+ <pre class="prettyprint"><code>//fpJson為buildKLinesTpSl產出之快取檔
4306
+ let r = loadKLinesTpSl('./cache/kltpsl.json')
4307
+ console.log(r.meta.nBars)
4308
+ // => 6
4309
+
4310
+ let orders = r.ordersFromBars('long', 5, ['2020-01-01T00:00:00', '2020-01-01T12:00:00'], { uTrade: 100, uIni: 1000 })
4311
+ console.log(orders.map((o) => `${o.timeStart} ${o.timeEnd || 'unsettled'} ${o.modeResult || '-'}`))
4312
+ // => [
4313
+ // '2020-01-01T00:00:00 2020-01-01T04:00:00 profit',
4314
+ // '2020-01-01T12:00:00 unsettled -'
4315
+ // ]
4316
+ console.log(orders[0].priceStart, orders[0].priceEnd, orders[0].uProfitOrLoss, orders[0].uEquity)
4317
+ // => 100 105 4.9 1004.9</code></pre>
4318
+
4319
+
4320
+
4321
+
4322
+ <h5 class="h5-parameters">Parameters:</h5>
4323
+
4324
+
4325
+ <table class="params">
4326
+ <thead>
4327
+ <tr>
4328
+
4329
+ <th>Name</th>
4330
+
4331
+
4332
+ <th>Type</th>
4333
+
4334
+
4335
+
4336
+
4337
+
4338
+ <th class="last">Description</th>
4339
+ </tr>
4340
+ </thead>
4341
+
4342
+ <tbody>
4343
+
4344
+
4345
+ <tr>
4346
+
4347
+ <td class="name"><code>fpJson</code></td>
4348
+
4349
+
4350
+ <td class="type">
4351
+
4352
+
4353
+ <span class="param-type">String</span>
4354
+
4355
+
4356
+
4357
+
4358
+ </td>
4359
+
4360
+
4361
+
4362
+
4363
+
4364
+ <td class="description last"><p>輸入buildKLinesTpSl產出之快取json檔案路徑字串</p></td>
4365
+ </tr>
4366
+
4367
+
4368
+ </tbody>
4369
+ </table>
4370
+
4371
+
4372
+
4373
+
4374
+
4375
+
4376
+
4377
+
4378
+
4379
+
4380
+
4381
+
4382
+
4383
+
4384
+
4385
+
4386
+ <h5 class="h5-returns">Returns:</h5>
4387
+
4388
+
4389
+ <div class="param-desc">
4390
+ <p>回傳物件,內含meta(快取設定物件)、bars(以進場時間為key之結果物件)與ordersFromBars(mode, tpsl, entryTimes, opt)訂單重建函數,函數之opt可給uTrade(每單金額,預設1)、uIni(初始資金,預設1000)、rFee(手續費率,預設0.0005)、maxExitTime(出場時間大於等於此值之單視為未平倉,預設null)與skipSort(呼叫端保證entryTimes已升序時可省排序,預設false),回傳訂單陣列,快取內查無之進場時間會被濾除,未結單各盈虧欄位留空</p>
4391
+ </div>
4392
+
4393
+
4394
+
4395
+ <dl class="param-type">
4396
+ <dt>
4397
+ Type
4398
+ </dt>
4399
+ <dd>
4400
+
4401
+ <span class="param-type">Object</span>
4402
+
4403
+
4404
+
4405
+ </dd>
4406
+ </dl>
4407
+
4408
+
4409
+
4410
+
4411
+
4412
+
4413
+
4414
+
4415
+
4416
+
4417
+ <h4 class="name" id="runStrategies"><span class="type-signature type-signature-async">(async) </span>runStrategies<span class="signature">(ott, strategies, funGetSeries, opt<span class="signature-attributes">opt</span>)</span><span class="type-signature"> &rarr; {Promise}</span></h4>
4418
+
4419
+
4420
+
4421
+
4422
+
4423
+
4424
+ <dl class="details">
4425
+
4426
+ <dt class="tag-description">Description:</dt>
4427
+ <dd class="tag-description"><ul class="dummy"><li><p>執行多策略回測</p>
4428
+ <p>逐策略呼叫runStrategy(withSummary:false),各單附加策略sid後合併並依timeStart排序
4429
+ 以各策略settings.uIni總和為初始資金呼叫calcSummary統計合併摘要
4430
+ 個別策略執行失敗(如時間點無參數無法下單)時強制略過</p>
4431
+ <p>Unit Test: <a href="https://github.com/yuda-lyu/w-trade-backtest/blob/master/test/unit-WTradeBacktest.test.mjs">Github</a></p></li></ul></dd>
4432
+
4433
+
4434
+
4435
+ <dt class="tag-source">Source:</dt>
4436
+ <dd class="tag-source"><ul class="dummy"><li>
4437
+ <a href="runStrategies.mjs.html">runStrategies.mjs</a>, <a href="runStrategies.mjs.html#line79">line 79</a>
4438
+ </li></ul></dd>
4439
+
4440
+
4441
+
4442
+
4443
+
4444
+
4445
+
4446
+
4447
+
4448
+
4449
+
4450
+
4451
+
4452
+
4453
+
4454
+
4455
+
4456
+
4457
+
4458
+
4459
+
4460
+
4461
+
4462
+
4463
+
4464
+
4465
+
4466
+
4467
+
4468
+
4469
+
4470
+ </dl>
4471
+
4472
+
4473
+
4474
+
4475
+
4476
+
4477
+
4478
+
4479
+
4480
+
4481
+
4482
+ <h5 class="h5-examples">Example</h5>
4483
+
4484
+ <pre class="prettyprint"><code>let arrOhlc = [
4485
+ { time: '2020-01-01T00:00:00', Open: 100, High: 101, Low: 99, Close: 100 },
4486
+ { time: '2020-01-01T04:00:00', Open: 100, High: 106, Low: 100, Close: 105 },
4487
+ { time: '2020-01-01T08:00:00', Open: 105, High: 107, Low: 102, Close: 103 },
4488
+ { time: '2020-01-01T12:00:00', Open: 103, High: 104, Low: 94, Close: 95 },
4489
+ { time: '2020-01-01T16:00:00', Open: 95, High: 98, Low: 92, Close: 93 },
4490
+ { time: '2020-01-01T20:00:00', Open: 93, High: 99, Low: 95, Close: 97 },
4491
+ ]
4492
+
4493
+ let arrSig = [
4494
+ { time: '2020-01-01T00:00:00', param: 1 },
4495
+ { time: '2020-01-01T04:00:00', param: 0 },
4496
+ { time: '2020-01-01T08:00:00', param: 1 },
4497
+ { time: '2020-01-01T12:00:00', param: 0 },
4498
+ { time: '2020-01-01T16:00:00', param: 0 },
4499
+ { time: '2020-01-01T20:00:00', param: 0 },
4500
+ ]
4501
+
4502
+ let funGetSeries = async (key) => {
4503
+ if (key === 'btc') {
4504
+ return arrOhlc
4505
+ }
4506
+ if (key === 'sig') {
4507
+ return arrSig
4508
+ }
4509
+ throw new Error(`invalid key[${key}]`)
4510
+ }
4511
+
4512
+ let settings = { uIni: 1000, uTrade: 100, rTakeProfit: 0.05, rStopLoss: 0.03, rFee: 0.0005 }
4513
+ let strategies = [
4514
+ { sid: 's1', mode: 'long', keyOhlc: 'btc', conds: [{ key: 'sig', sym: '>', th: 0.5, opr: 'and' }], settings },
4515
+ { sid: 's2', mode: 'short', keyOhlc: 'btc', conds: [{ key: 'sig', sym: '&lt;', th: 0.5, opr: 'and' }], settings },
4516
+ ]
4517
+
4518
+ let rr = await runStrategies(ott, strategies, funGetSeries)
4519
+ console.log(rr.orders.map((o) => `${o.sid} ${o.timeStart} ${o.mode} ${o.modeResult || 'unsettled'}`))
4520
+ // => [
4521
+ // 's1 2020-01-01T00:00:00 long profit',
4522
+ // 's2 2020-01-01T04:00:00 short profit',
4523
+ // 's1 2020-01-01T08:00:00 long loss',
4524
+ // 's2 2020-01-01T12:00:00 short loss',
4525
+ // 's2 2020-01-01T16:00:00 short loss',
4526
+ // 's2 2020-01-01T20:00:00 short unsettled'
4527
+ // ]
4528
+ console.log(rr.summary.uIni, rr.summary.numTrade, rr.summary.rWin)
4529
+ // => 2000 6 40.00%</code></pre>
4530
+
4531
+
4532
+
4533
+
4534
+ <h5 class="h5-parameters">Parameters:</h5>
4535
+
4536
+
4537
+ <table class="params">
4538
+ <thead>
4539
+ <tr>
4540
+
4541
+ <th>Name</th>
4542
+
2881
4543
 
2882
-
4544
+ <th>Type</th>
2883
4545
 
2884
-
2885
- </td>
2886
-
4546
+
4547
+ <th>Attributes</th>
4548
+
2887
4549
 
2888
-
2889
- <td class="default">
2890
-
2891
- <code>''</code>
2892
-
2893
- </td>
2894
-
4550
+
4551
+ <th>Default</th>
4552
+
2895
4553
 
2896
- <td class="description last"><p>輸入報表標題字串,預設為orders.json所在資料夾名</p></td>
2897
- </tr>
4554
+ <th class="last">Description</th>
4555
+ </tr>
4556
+ </thead>
2898
4557
 
4558
+ <tbody>
2899
4559
 
2900
4560
 
2901
4561
  <tr>
2902
4562
 
2903
- <td class="name"><code>uIni</code></td>
4563
+ <td class="name"><code>ott</code></td>
2904
4564
 
2905
4565
 
2906
4566
  <td class="type">
2907
4567
 
2908
4568
 
2909
- <span class="param-type">Number</span>
4569
+ <span class="param-type">function</span>
2910
4570
 
2911
4571
 
2912
4572
 
@@ -2916,8 +4576,6 @@ fpOrders非有效字串或非檔案、內容非有效陣列時throw</p>
2916
4576
 
2917
4577
  <td class="attributes">
2918
4578
 
2919
- &lt;optional><br>
2920
-
2921
4579
 
2922
4580
 
2923
4581
 
@@ -2928,25 +4586,23 @@ fpOrders非有效字串或非檔案、內容非有效陣列時throw</p>
2928
4586
 
2929
4587
  <td class="default">
2930
4588
 
2931
- <code>null</code>
2932
-
2933
4589
  </td>
2934
4590
 
2935
4591
 
2936
- <td class="description last"><p>輸入初始資金數值,預設由首筆已結算單推回(uEquity - uCumuProfitOrLoss),推不出則為1000</p></td>
4592
+ <td class="description last"><p>輸入時區時間函數,傳入時間字串回傳dayjs時間物件(可用src/ott.mjs或自行以dayjs包裝)</p></td>
2937
4593
  </tr>
2938
4594
 
2939
4595
 
2940
4596
 
2941
4597
  <tr>
2942
4598
 
2943
- <td class="name"><code>timeOhlcStart</code></td>
4599
+ <td class="name"><code>strategies</code></td>
2944
4600
 
2945
4601
 
2946
4602
  <td class="type">
2947
4603
 
2948
4604
 
2949
- <span class="param-type">String</span>
4605
+ <span class="param-type">Array</span>
2950
4606
 
2951
4607
 
2952
4608
 
@@ -2956,8 +4612,6 @@ fpOrders非有效字串或非檔案、內容非有效陣列時throw</p>
2956
4612
 
2957
4613
  <td class="attributes">
2958
4614
 
2959
- &lt;optional><br>
2960
-
2961
4615
 
2962
4616
 
2963
4617
 
@@ -2968,25 +4622,23 @@ fpOrders非有效字串或非檔案、內容非有效陣列時throw</p>
2968
4622
 
2969
4623
  <td class="default">
2970
4624
 
2971
- <code>''</code>
2972
-
2973
4625
  </td>
2974
4626
 
2975
4627
 
2976
- <td class="description last"><p>輸入摘要統計起始秒時間字串,影響btDays與年化,預設由訂單最早timeStart推得,注意訂單起訖僅為「有單的範圍」,若實際回測窗較寬(頭尾無單)年化會被高估,建議明給</p></td>
4628
+ <td class="description last"><p>輸入策略陣列,各元素需含sid與runStrategy之strategy欄位</p></td>
2977
4629
  </tr>
2978
4630
 
2979
4631
 
2980
4632
 
2981
4633
  <tr>
2982
4634
 
2983
- <td class="name"><code>timeOhlcEnd</code></td>
4635
+ <td class="name"><code>funGetSeries</code></td>
2984
4636
 
2985
4637
 
2986
4638
  <td class="type">
2987
4639
 
2988
4640
 
2989
- <span class="param-type">String</span>
4641
+ <span class="param-type">function</span>
2990
4642
 
2991
4643
 
2992
4644
 
@@ -2996,8 +4648,6 @@ fpOrders非有效字串或非檔案、內容非有效陣列時throw</p>
2996
4648
 
2997
4649
  <td class="attributes">
2998
4650
 
2999
- &lt;optional><br>
3000
-
3001
4651
 
3002
4652
 
3003
4653
 
@@ -3008,25 +4658,23 @@ fpOrders非有效字串或非檔案、內容非有效陣列時throw</p>
3008
4658
 
3009
4659
  <td class="default">
3010
4660
 
3011
- <code>''</code>
3012
-
3013
4661
  </td>
3014
4662
 
3015
4663
 
3016
- <td class="description last"><p>輸入摘要統計結束秒時間字串,預設由訂單最晚timeEnd(未平倉單取timeStart)推得</p></td>
4664
+ <td class="description last"><p>輸入序列查詢async函數,依key回傳時間序列陣列</p></td>
3017
4665
  </tr>
3018
4666
 
3019
4667
 
3020
4668
 
3021
4669
  <tr>
3022
4670
 
3023
- <td class="name"><code>withWriteSummary</code></td>
4671
+ <td class="name"><code>opt</code></td>
3024
4672
 
3025
4673
 
3026
4674
  <td class="type">
3027
4675
 
3028
4676
 
3029
- <span class="param-type">Boolean</span>
4677
+ <span class="param-type">Object</span>
3030
4678
 
3031
4679
 
3032
4680
 
@@ -3048,146 +4696,14 @@ fpOrders非有效字串或非檔案、內容非有效陣列時throw</p>
3048
4696
 
3049
4697
  <td class="default">
3050
4698
 
3051
- <code>false</code>
4699
+ <code>{}</code>
3052
4700
 
3053
4701
  </td>
3054
4702
 
3055
4703
 
3056
- <td class="description last"><p>輸入是否同時輸出summary.json(與fpOut同資料夾)布林值,預設false</p></td>
3057
- </tr>
3058
-
3059
-
3060
- </tbody>
3061
- </table>
3062
-
3063
- </td>
3064
- </tr>
3065
-
3066
-
3067
- </tbody>
3068
- </table>
3069
-
3070
-
3071
-
3072
-
3073
-
3074
-
3075
-
3076
-
3077
-
3078
-
3079
-
3080
-
3081
-
3082
-
3083
-
3084
-
3085
- <h5 class="h5-returns">Returns:</h5>
3086
-
3087
-
3088
- <div class="param-desc">
3089
- <p>回傳Promise,resolve為物件,內含orders(訂單陣列)、summary(摘要物件)、fpOut(輸出html路徑)欄位</p>
3090
- </div>
3091
-
3092
-
3093
-
3094
- <dl class="param-type">
3095
- <dt>
3096
- Type
3097
- </dt>
3098
- <dd>
3099
-
3100
- <span class="param-type">Promise</span>
3101
-
3102
-
3103
-
3104
- </dd>
3105
- </dl>
3106
-
3107
-
3108
-
3109
-
3110
-
3111
-
3112
-
3113
-
3114
-
3115
-
3116
- <h4 class="name" id="genReportCore"><span class="type-signature"></span>genReportCore<span class="signature">(r, fpOut)</span><span class="type-signature"> &rarr; {undefined}</span></h4>
3117
-
3118
-
3119
-
3120
-
3121
-
3122
-
3123
- <dl class="details">
3124
-
3125
- <dt class="tag-description">Description:</dt>
3126
- <dd class="tag-description"><ul class="dummy"><li><p>產出html回測報告</p>
3127
- <p>讀取與本模組同資料夾之模板資產(tmp.html與render*.js),置換{name}、{orders}、{summary}後寫出html
3128
- 報告內含權益曲線、訂單表格、時間軸與摘要</p>
3129
- <p>Unit Test: <a href="https://github.com/yuda-lyu/w-trade-backtest/blob/master/test/unit-WTradeBacktest.test.mjs">Github</a></p></li></ul></dd>
3130
-
3131
-
3132
-
3133
- <dt class="tag-source">Source:</dt>
3134
- <dd class="tag-source"><ul class="dummy"><li>
3135
- <a href="genReportCore.mjs.html">genReportCore.mjs</a>, <a href="genReportCore.mjs.html#line28">line 28</a>
3136
- </li></ul></dd>
3137
-
3138
-
3139
-
3140
-
3141
-
3142
-
3143
-
3144
-
3145
-
3146
-
3147
-
3148
-
3149
-
3150
-
3151
-
3152
-
3153
-
3154
-
3155
-
3156
-
3157
-
3158
-
3159
-
3160
-
3161
-
3162
-
3163
-
3164
-
3165
-
3166
-
3167
-
3168
- </dl>
3169
-
3170
-
3171
-
3172
-
3173
-
3174
-
3175
-
3176
-
3177
-
3178
-
3179
-
3180
- <h5 class="h5-examples">Example</h5>
3181
-
3182
- <pre class="prettyprint"><code>//rr為runStrategies範例之回傳{orders,summary}
3183
- genReportCore({ name: '示範策略', orders: rr.orders, summary: rr.summary }, './report.html')
3184
- // => 於'./report.html'寫出html報告</code></pre>
3185
-
3186
-
3187
-
3188
-
3189
- <h5 class="h5-parameters">Parameters:</h5>
3190
-
4704
+ <td class="description last"><p>輸入設定物件,預設{}</p>
4705
+ <h6>Properties</h6>
4706
+
3191
4707
 
3192
4708
  <table class="params">
3193
4709
  <thead>
@@ -3199,8 +4715,12 @@ genReportCore({ name: '示範策略', orders: rr.orders, summary: rr.summary },
3199
4715
  <th>Type</th>
3200
4716
 
3201
4717
 
4718
+ <th>Attributes</th>
4719
+
3202
4720
 
3203
4721
 
4722
+ <th>Default</th>
4723
+
3204
4724
 
3205
4725
  <th class="last">Description</th>
3206
4726
  </tr>
@@ -3211,13 +4731,13 @@ genReportCore({ name: '示範策略', orders: rr.orders, summary: rr.summary },
3211
4731
 
3212
4732
  <tr>
3213
4733
 
3214
- <td class="name"><code>r</code></td>
4734
+ <td class="name"><code>withCalcOrderProfitOrLoss</code></td>
3215
4735
 
3216
4736
 
3217
4737
  <td class="type">
3218
4738
 
3219
4739
 
3220
- <span class="param-type">Object</span>
4740
+ <span class="param-type">Boolean</span>
3221
4741
 
3222
4742
 
3223
4743
 
@@ -3225,23 +4745,39 @@ genReportCore({ name: '示範策略', orders: rr.orders, summary: rr.summary },
3225
4745
  </td>
3226
4746
 
3227
4747
 
4748
+ <td class="attributes">
4749
+
4750
+ &lt;optional><br>
4751
+
3228
4752
 
4753
+
4754
+
4755
+
4756
+ </td>
3229
4757
 
3230
4758
 
3231
- <td class="description last"><p>輸入報告物件,需含name(報告名稱字串)、orders(訂單陣列)、summary(摘要物件)欄位</p></td>
4759
+
4760
+ <td class="default">
4761
+
4762
+ <code>true</code>
4763
+
4764
+ </td>
4765
+
4766
+
4767
+ <td class="description last"><p>輸入是否經calcOrders結算訂單布林值,預設true</p></td>
3232
4768
  </tr>
3233
4769
 
3234
4770
 
3235
4771
 
3236
4772
  <tr>
3237
4773
 
3238
- <td class="name"><code>fpOut</code></td>
4774
+ <td class="name"><code>withSummary</code></td>
3239
4775
 
3240
4776
 
3241
4777
  <td class="type">
3242
4778
 
3243
4779
 
3244
- <span class="param-type">String</span>
4780
+ <span class="param-type">Boolean</span>
3245
4781
 
3246
4782
 
3247
4783
 
@@ -3249,10 +4785,33 @@ genReportCore({ name: '示範策略', orders: rr.orders, summary: rr.summary },
3249
4785
  </td>
3250
4786
 
3251
4787
 
4788
+ <td class="attributes">
4789
+
4790
+ &lt;optional><br>
4791
+
4792
+
4793
+
4794
+
4795
+
4796
+ </td>
4797
+
3252
4798
 
3253
4799
 
4800
+ <td class="default">
4801
+
4802
+ <code>true</code>
4803
+
4804
+ </td>
4805
+
4806
+
4807
+ <td class="description last"><p>輸入是否計算統計摘要布林值,預設true</p></td>
4808
+ </tr>
4809
+
4810
+
4811
+ </tbody>
4812
+ </table>
3254
4813
 
3255
- <td class="description last"><p>輸入輸出html檔案路徑字串</p></td>
4814
+ </td>
3256
4815
  </tr>
3257
4816
 
3258
4817
 
@@ -3278,7 +4837,7 @@ genReportCore({ name: '示範策略', orders: rr.orders, summary: rr.summary },
3278
4837
 
3279
4838
 
3280
4839
  <div class="param-desc">
3281
- <p>無回傳,於fpOut寫出html報告</p>
4840
+ <p>回傳Promise,resolve為{orders,summary}物件</p>
3282
4841
  </div>
3283
4842
 
3284
4843
 
@@ -3289,7 +4848,7 @@ genReportCore({ name: '示範策略', orders: rr.orders, summary: rr.summary },
3289
4848
  </dt>
3290
4849
  <dd>
3291
4850
 
3292
- <span class="param-type">undefined</span>
4851
+ <span class="param-type">Promise</span>
3293
4852
 
3294
4853
 
3295
4854
 
@@ -3305,7 +4864,7 @@ genReportCore({ name: '示範策略', orders: rr.orders, summary: rr.summary },
3305
4864
 
3306
4865
 
3307
4866
 
3308
- <h4 class="name" id="runStrategies"><span class="type-signature type-signature-async">(async) </span>runStrategies<span class="signature">(ott, strategies, funGetSeries, opt<span class="signature-attributes">opt</span>)</span><span class="type-signature"> &rarr; {Promise}</span></h4>
4867
+ <h4 class="name" id="runStrategiesAndBacktest"><span class="type-signature type-signature-async">(async) </span>runStrategiesAndBacktest<span class="signature">(ott, fdOhlc, fdParam, strategies, timeStart, timeEnd, fdTest, opt<span class="signature-attributes">opt</span>)</span><span class="type-signature"> &rarr; {Promise}</span></h4>
3309
4868
 
3310
4869
 
3311
4870
 
@@ -3315,17 +4874,17 @@ genReportCore({ name: '示範策略', orders: rr.orders, summary: rr.summary },
3315
4874
  <dl class="details">
3316
4875
 
3317
4876
  <dt class="tag-description">Description:</dt>
3318
- <dd class="tag-description"><ul class="dummy"><li><p>執行多策略回測</p>
3319
- <p>逐策略呼叫runStrategy(withSummary:false),各單附加策略sid後合併並依timeStart排序
3320
- 以各策略settings.uIni總和為初始資金呼叫calcSummary統計合併摘要
3321
- 個別策略執行失敗(如時間點無參數無法下單)時強制略過</p>
4877
+ <dd class="tag-description"><ul class="dummy"><li><p>執行多策略回測並輸出訂單、摘要與報告檔案</p>
4878
+ <p>以w-data-tdprovide讀取fdOhlc與fdParam資料夾數據,建立timeStart至timeEnd範圍之序列查詢函數後執行runStrategies
4879
+ 合併結果命名為'全部策略',並輸出orders.json、summary.json、report.html至fdTest資料夾
4880
+ fdOhlc或fdParam非資料夾、strategies非有效陣列時throw</p>
3322
4881
  <p>Unit Test: <a href="https://github.com/yuda-lyu/w-trade-backtest/blob/master/test/unit-WTradeBacktest.test.mjs">Github</a></p></li></ul></dd>
3323
4882
 
3324
4883
 
3325
4884
 
3326
4885
  <dt class="tag-source">Source:</dt>
3327
4886
  <dd class="tag-source"><ul class="dummy"><li>
3328
- <a href="runStrategies.mjs.html">runStrategies.mjs</a>, <a href="runStrategies.mjs.html#line79">line 79</a>
4887
+ <a href="runStrategiesAndBacktest.mjs.html">runStrategiesAndBacktest.mjs</a>, <a href="runStrategiesAndBacktest.mjs.html#line74">line 74</a>
3329
4888
  </li></ul></dd>
3330
4889
 
3331
4890
 
@@ -3372,52 +4931,7 @@ genReportCore({ name: '示範策略', orders: rr.orders, summary: rr.summary },
3372
4931
 
3373
4932
  <h5 class="h5-examples">Example</h5>
3374
4933
 
3375
- <pre class="prettyprint"><code>let arrOhlc = [
3376
- { time: '2020-01-01T00:00:00', Open: 100, High: 101, Low: 99, Close: 100 },
3377
- { time: '2020-01-01T04:00:00', Open: 100, High: 106, Low: 100, Close: 105 },
3378
- { time: '2020-01-01T08:00:00', Open: 105, High: 107, Low: 102, Close: 103 },
3379
- { time: '2020-01-01T12:00:00', Open: 103, High: 104, Low: 94, Close: 95 },
3380
- { time: '2020-01-01T16:00:00', Open: 95, High: 98, Low: 92, Close: 93 },
3381
- { time: '2020-01-01T20:00:00', Open: 93, High: 99, Low: 95, Close: 97 },
3382
- ]
3383
-
3384
- let arrSig = [
3385
- { time: '2020-01-01T00:00:00', param: 1 },
3386
- { time: '2020-01-01T04:00:00', param: 0 },
3387
- { time: '2020-01-01T08:00:00', param: 1 },
3388
- { time: '2020-01-01T12:00:00', param: 0 },
3389
- { time: '2020-01-01T16:00:00', param: 0 },
3390
- { time: '2020-01-01T20:00:00', param: 0 },
3391
- ]
3392
-
3393
- let funGetSeries = async (key) => {
3394
- if (key === 'btc') {
3395
- return arrOhlc
3396
- }
3397
- if (key === 'sig') {
3398
- return arrSig
3399
- }
3400
- throw new Error(`invalid key[${key}]`)
3401
- }
3402
-
3403
- let settings = { uIni: 1000, uTrade: 100, rTakeProfit: 0.05, rStopLoss: 0.03, rFee: 0.0005 }
3404
- let strategies = [
3405
- { sid: 's1', mode: 'long', keyOhlc: 'btc', conds: [{ key: 'sig', sym: '>', th: 0.5, opr: 'and' }], settings },
3406
- { sid: 's2', mode: 'short', keyOhlc: 'btc', conds: [{ key: 'sig', sym: '&lt;', th: 0.5, opr: 'and' }], settings },
3407
- ]
3408
-
3409
- let rr = await runStrategies(ott, strategies, funGetSeries)
3410
- console.log(rr.orders.map((o) => `${o.sid} ${o.timeStart} ${o.mode} ${o.modeResult || 'unsettled'}`))
3411
- // => [
3412
- // 's1 2020-01-01T00:00:00 long profit',
3413
- // 's2 2020-01-01T04:00:00 short profit',
3414
- // 's1 2020-01-01T08:00:00 long loss',
3415
- // 's2 2020-01-01T12:00:00 short loss',
3416
- // 's2 2020-01-01T16:00:00 short loss',
3417
- // 's2 2020-01-01T20:00:00 short unsettled'
3418
- // ]
3419
- console.log(rr.summary.uIni, rr.summary.numTrade, rr.summary.rWin)
3420
- // => 2000 6 40.00%</code></pre>
4934
+ <pre class="prettyprint"><code>import fs from 'fs'
3421
4935
  { time: '2020-01-01T00:00:00', Open: 100, High: 101, Low: 99, Close: 100 },
3422
4936
  { time: '2020-01-01T04:00:00', Open: 100, High: 106, Low: 100, Close: 105 },
3423
4937
  { time: '2020-01-01T08:00:00', Open: 105, High: 107, Low: 102, Close: 103 },
3424
4938
  { time: '2020-01-01T12:00:00', Open: 103, High: 104, Low: 94, Close: 95 },
3425
4939
  { time: '2020-01-01T16:00:00', Open: 95, High: 98, Low: 92, Close: 93 },
3426
4940
  { time: '2020-01-01T20:00:00', Open: 93, High: 99, Low: 95, Close: 97 },
3427
4941
  { time: '2020-01-01T00:00:00', param: 1 },
3428
4942
  { time: '2020-01-01T04:00:00', param: 0 },
3429
4943
  { time: '2020-01-01T08:00:00', param: 1 },
3430
4944
  { time: '2020-01-01T12:00:00', param: 0 },
3431
4945
  { time: '2020-01-01T16:00:00', param: 0 },
3432
4946
  { time: '2020-01-01T20:00:00', param: 0 },
3433
4947
  { sid: 's1', mode: 'long', keyOhlc: 'btc', conds: [{ key: 'sig', sym: '>', th: 0.5, opr: 'and' }], settings },
3434
4948
  { sid: 's2', mode: 'short', keyOhlc: 'btc', conds: [{ key: 'sig', sym: '&lt;', th: 0.5, opr: 'and' }], settings },
3435
4949
 
3436
4950
 
3437
4951
 
@@ -3485,6 +4999,78 @@ console.log(rr.summary.uIni, rr.summary.numTrade, rr.summary.rWin)
3485
4999
 
3486
5000
 
3487
5001
 
5002
+ <tr>
5003
+
5004
+ <td class="name"><code>fdOhlc</code></td>
5005
+
5006
+
5007
+ <td class="type">
5008
+
5009
+
5010
+ <span class="param-type">String</span>
5011
+
5012
+
5013
+
5014
+
5015
+ </td>
5016
+
5017
+
5018
+ <td class="attributes">
5019
+
5020
+
5021
+
5022
+
5023
+
5024
+ </td>
5025
+
5026
+
5027
+
5028
+ <td class="default">
5029
+
5030
+ </td>
5031
+
5032
+
5033
+ <td class="description last"><p>輸入儲存K線(ohlc)序列資料夾字串,各序列以<code>${key}.json</code>儲存</p></td>
5034
+ </tr>
5035
+
5036
+
5037
+
5038
+ <tr>
5039
+
5040
+ <td class="name"><code>fdParam</code></td>
5041
+
5042
+
5043
+ <td class="type">
5044
+
5045
+
5046
+ <span class="param-type">String</span>
5047
+
5048
+
5049
+
5050
+
5051
+ </td>
5052
+
5053
+
5054
+ <td class="attributes">
5055
+
5056
+
5057
+
5058
+
5059
+
5060
+ </td>
5061
+
5062
+
5063
+
5064
+ <td class="default">
5065
+
5066
+ </td>
5067
+
5068
+
5069
+ <td class="description last"><p>輸入儲存指標參數序列資料夾字串</p></td>
5070
+ </tr>
5071
+
5072
+
5073
+
3488
5074
  <tr>
3489
5075
 
3490
5076
  <td class="name"><code>strategies</code></td>
@@ -3523,13 +5109,13 @@ console.log(rr.summary.uIni, rr.summary.numTrade, rr.summary.rWin)
3523
5109
 
3524
5110
  <tr>
3525
5111
 
3526
- <td class="name"><code>funGetSeries</code></td>
5112
+ <td class="name"><code>timeStart</code></td>
3527
5113
 
3528
5114
 
3529
5115
  <td class="type">
3530
5116
 
3531
5117
 
3532
- <span class="param-type">function</span>
5118
+ <span class="param-type">String</span>
3533
5119
 
3534
5120
 
3535
5121
 
@@ -3552,7 +5138,79 @@ console.log(rr.summary.uIni, rr.summary.numTrade, rr.summary.rWin)
3552
5138
  </td>
3553
5139
 
3554
5140
 
3555
- <td class="description last"><p>輸入序列查詢async函數,依key回傳時間序列陣列</p></td>
5141
+ <td class="description last"><p>輸入回測起始秒時間字串</p></td>
5142
+ </tr>
5143
+
5144
+
5145
+
5146
+ <tr>
5147
+
5148
+ <td class="name"><code>timeEnd</code></td>
5149
+
5150
+
5151
+ <td class="type">
5152
+
5153
+
5154
+ <span class="param-type">String</span>
5155
+
5156
+
5157
+
5158
+
5159
+ </td>
5160
+
5161
+
5162
+ <td class="attributes">
5163
+
5164
+
5165
+
5166
+
5167
+
5168
+ </td>
5169
+
5170
+
5171
+
5172
+ <td class="default">
5173
+
5174
+ </td>
5175
+
5176
+
5177
+ <td class="description last"><p>輸入回測結束秒時間字串</p></td>
5178
+ </tr>
5179
+
5180
+
5181
+
5182
+ <tr>
5183
+
5184
+ <td class="name"><code>fdTest</code></td>
5185
+
5186
+
5187
+ <td class="type">
5188
+
5189
+
5190
+ <span class="param-type">String</span>
5191
+
5192
+
5193
+
5194
+
5195
+ </td>
5196
+
5197
+
5198
+ <td class="attributes">
5199
+
5200
+
5201
+
5202
+
5203
+
5204
+ </td>
5205
+
5206
+
5207
+
5208
+ <td class="default">
5209
+
5210
+ </td>
5211
+
5212
+
5213
+ <td class="description last"><p>輸入輸出結果資料夾字串</p></td>
3556
5214
  </tr>
3557
5215
 
3558
5216
 
@@ -3622,7 +5280,7 @@ console.log(rr.summary.uIni, rr.summary.numTrade, rr.summary.rWin)
3622
5280
 
3623
5281
  <tr>
3624
5282
 
3625
- <td class="name"><code>withCalcOrderProfitOrLoss</code></td>
5283
+ <td class="name"><code>writeOrders</code></td>
3626
5284
 
3627
5285
 
3628
5286
  <td class="type">
@@ -3655,14 +5313,14 @@ console.log(rr.summary.uIni, rr.summary.numTrade, rr.summary.rWin)
3655
5313
  </td>
3656
5314
 
3657
5315
 
3658
- <td class="description last"><p>輸入是否經calcOrders結算訂單布林值,預設true</p></td>
5316
+ <td class="description last"><p>輸入是否輸出orders.json布林值,預設true</p></td>
3659
5317
  </tr>
3660
5318
 
3661
5319
 
3662
5320
 
3663
5321
  <tr>
3664
5322
 
3665
- <td class="name"><code>withSummary</code></td>
5323
+ <td class="name"><code>writeSummary</code></td>
3666
5324
 
3667
5325
 
3668
5326
  <td class="type">
@@ -3695,7 +5353,47 @@ console.log(rr.summary.uIni, rr.summary.numTrade, rr.summary.rWin)
3695
5353
  </td>
3696
5354
 
3697
5355
 
3698
- <td class="description last"><p>輸入是否計算統計摘要布林值,預設true</p></td>
5356
+ <td class="description last"><p>輸入是否輸出summary.json布林值,預設true</p></td>
5357
+ </tr>
5358
+
5359
+
5360
+
5361
+ <tr>
5362
+
5363
+ <td class="name"><code>writeReport</code></td>
5364
+
5365
+
5366
+ <td class="type">
5367
+
5368
+
5369
+ <span class="param-type">Boolean</span>
5370
+
5371
+
5372
+
5373
+
5374
+ </td>
5375
+
5376
+
5377
+ <td class="attributes">
5378
+
5379
+ &lt;optional><br>
5380
+
5381
+
5382
+
5383
+
5384
+
5385
+ </td>
5386
+
5387
+
5388
+
5389
+ <td class="default">
5390
+
5391
+ <code>true</code>
5392
+
5393
+ </td>
5394
+
5395
+
5396
+ <td class="description last"><p>輸入是否輸出report.html布林值,預設true</p></td>
3699
5397
  </tr>
3700
5398
 
3701
5399
 
@@ -3728,7 +5426,7 @@ console.log(rr.summary.uIni, rr.summary.numTrade, rr.summary.rWin)
3728
5426
 
3729
5427
 
3730
5428
  <div class="param-desc">
3731
- <p>回傳Promise,resolve為{orders,summary}物件</p>
5429
+ <p>回傳Promise,resolve為{name,orders,summary}物件,另於fdTest輸出結果檔案</p>
3732
5430
  </div>
3733
5431
 
3734
5432
 
@@ -4218,7 +5916,7 @@ console.log(r.summary.numTrade, r.summary.rWin, r.summary.uEquityFinal)
4218
5916
  <br class="clear">
4219
5917
 
4220
5918
  <footer>
4221
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Sun Aug 02 2026 20:09:43 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
5919
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Mon Aug 03 2026 14:28:31 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
4222
5920
  </footer>
4223
5921
 
4224
5922
  <script>prettyPrint();</script>