S4-LAB · backtest งานแรกตั้งแต่ต้นจนจบ
▶ clip: https://youtu.be/j4GVsxiy404
จบบทนี้แล้วทำได้:
- ตั้งช่วงทดสอบจาก
is_oosโดยไม่พิมพ์วันที่เอง - เขียนเกณฑ์ผ่าน/ตกและลงบัญชี Šidák ก่อนกด run
- ตรวจแผนงานด้วย
--dry-runแล้วเข้า queue ผ่าน dashboard - หา file รายงาน อ่าน History Quality ก่อนตัวเลขอื่น แล้วใช้
mcกับverdictอ่านผล - บันทึกคำตัดสินลง
research\status.yamlและตรวจด้วยea_status --check
ต้องมีก่อน: ทำ M0-LAB จบแล้ว · มีบัญชี demo อย่างน้อย 1 บัญชี (ใน clip คือ RoboForex demo) · bt\ea-bt.exe tick_depth --terminal mt5\MT5_<ชื่อ> --from 2026-01 ตอบ yes แล้ว
EA ที่ใช้คือ LAB_MACROSS v1.00 ที่มากับ kit (eas\LAB_MACROSS\LAB_MACROSS_v1.00.mq5) · ทุกคำสั่งพิมพ์ใน PowerShell ที่ folder kit (C:\ea-research-starter ใน clip) · ขั้นตอนตรงกับ README.md ของ kit หัวข้อ "lab แรก" ข้อ 1–7 และข้อ 8 ของ "ทดสอบ EA ของตัวเอง"
clip นี้ไม่มีเสียงพูด อ่าน subtitle แทน และไม่มี slide บทอ่านนี้จึงไม่มีภาพ
1 · เอาช่วงทดสอบจาก is_oos
bt\ea-bt.exe is_oos --year 2026 --yaml
ผลคือ date_from / date_to ของ IS 2026 = 2026-01-01 → 2026-04-30
แล้วเปิด bt\config.yaml ดู date_from กับ date_to — kit ตั้งค่านี้ไว้ตรงกันแล้ว
ทำไมห้ามพิมพ์วันที่เอง: ช่วง IS/OOS ของแต่ละปีถูกสุ่มครั้งเดียวแล้ว lock ไว้ ถ้าเลือกวันที่เองหลังเคยเห็นผล ก็คือเลือกช่วงที่ผลออกมาถูกใจ ซึ่งทำให้การแยก IS กับ OOS ไม่มีความหมาย
tester หยุดที่ 00:00 ของ date_to — วันที่ 30 เม.ย. จึงไม่ถูก run
ต่างจาก clip: ตอนอัด config ยังตั้ง
deposit: 1000· kit ปัจจุบันตั้งdeposit: 10000เหตุผลเขียนไว้ในbt\config.yaml: risk 1% ÷ (SL $10 × contract 100) ได้ 0.01 lot ซึ่งเท่ากับขั้นต่ำพอดี พอขาดทุน trade แรก lot ปัดลงเหลือ 0 แล้ว EA หยุดยิงทั้งรอบ (เกิดจริงใน sandbox 2026-11-01: 3 trade แล้วเงียบ 4 เดือน) · ห้ามลดกลับเป็น 1,000
2 · เขียนเกณฑ์ก่อน run
เปิด bt\config.yaml คู่กับ research\3-prereg\prereg-template.md
- เขียนเกณฑ์ผ่าน/ตก S1–S6 ในหัว
bt\config.yamlทุกบรรทัดขึ้นต้นด้วย#— การเขียนไว้ก่อน run นับเป็น prereg - ใช้เกณฑ์จากตารางข้อ 4 ของ template (ที่มาเต็มอยู่ใน
docs\ea-screen-criteria.md):
| รหัส | criteria | ผ่านเมื่อ |
|---|---|---|
| S1 | ข้อมูลใช้ได้ | history_quality ≥ 90% |
| S2 | trade กระจายพอ | ≥ 10 วันที่มี trade |
| S3 | edge | E[R] > 0 และ CI ล่าง > 0 (bootstrap รายวัน) · t ≥ ค่าจาก ledger |
| S4 | ไม่พึ่ง tail | ตัด 3 trade บนสุดแล้วยังบวก |
| S5 | ความเสี่ยง | Equity DD Relative ≤ 30% |
| S6 | เกินฐานรูปทรง | win% > 1 / (1 + payoff) |
- เปิด
research\3-prereg\sidak-ledger.mdเพิ่มแถวที่ 1 · ช่อง "ผล" เว้นไว้ กรอกหลัง verdict - บันทึกทั้งสอง file
เขียนแล้วห้ามแก้หลังเห็นผล ถ้าพบทีหลังว่าเกณฑ์ตั้งผิด ให้เขียนเพิ่มว่าผิดตรงไหน ไม่ใช่แก้ทับ
ทำไมต้องลงบัญชี Šidák: ยิ่งทดสอบหลายครั้ง โอกาสที่จะเจอ "ผ่าน" จากโชคล้วนยิ่งสูง (sidak-ledger.md ยกตัวอย่าง k = 10 ที่ α = 5% → โอกาสผ่านเพราะโชค 40%) เกณฑ์ t จึงต้องเข้มขึ้นตามจำนวนการทดสอบ ถ้าไม่จดไว้ก็ไม่รู้ว่าต้องเข้มขึ้นเท่าไร
ต่างจาก clip: ใน clip พิมพ์ S3 เป็น
t >= 1.96·verdictใช้เส้นขั้นต่ำ 2.0 (G4_MIN_Tใน code) ให้เขียนt ≥ 2.0template ข้อ 2–3 ยังเขียนคำสั่งเป็น
python bt/...· ในเครื่องผู้เรียนไม่มี Python ให้ใช้รูปbt\ea-bt.exe <เครื่องมือ>แทน เช่นbt\ea-bt.exe is_oos --year 2026 --yaml
3 · dry-run ตรวจแผนงาน
bt\ea-bt.exe run --config bt\config.yaml --dry-run
dry-run พิมพ์แผนงานออกมาให้ดูอย่างเดียว ยังไม่ run จริง ตรวจว่า:
- หนึ่งงานต่อหนึ่งบัญชี (มี 1 บัญชีก็ต้องได้ 1 งาน)
- EA
LAB_MACROSS· presetV1.00/default· periodH1· วันที่ 2026-01-01 → 2026-04-30
ถ้าเห็น ⚠ .ex5 not found แล้วบรรทัดท้ายเป็น (dry-run) would run 1 jobs ไม่ต้องทำอะไร — kit มีแต่ .mq5 และ run จะ compile ให้เองก่อน backtest
4 · เข้า queue แล้วกดเริ่ม
- เปิด dashboard (
2-เปิดหน้าคุม.bat) → tab ระบบ backtest → card queue งาน - ช่อง file config เลือก
config.yaml— dashboard ใช้ file ที่เลือกตรง ๆ ไม่ได้สร้างสำเนา - กด + เพิ่มงานนี้เข้า queue → แถวใหม่ขึ้นสถานะ "รอ"
- กด "เริ่ม queue" เอง ระบบไม่เริ่มให้
- MT5 เปิดเอง run เสร็จแล้วปิดเอง แถวใน queue เปลี่ยนเป็น "เสร็จ"
queue เก็บ config ทั้งก้อนไว้ตอนกดเพิ่ม แก้ YAML หลังจากนั้นไม่ถึงงานที่รออยู่ ต้องเอางานออกแล้วเพิ่มใหม่ (ดู S4)
เรื่อง tick ครั้งแรก:
- ถ้าดึง tick ไว้ก่อนด้วย
tick_depth --from 2026-01แล้ว (แบบใน clip) MT5 เริ่ม run ได้เลย · ใน clip การดึง tick ม.ค.–เม.ย. 2026 ใช้ราว 3 นาที และ run backtest เองใช้ 21 วินาที - ถ้ายังไม่ได้ดึง MT5 จะโหลด tick จาก broker ก่อน ดูได้ที่ "Download history: xx%" มุมขวาล่างของ Strategy Tester ระหว่างนั้นเส้นทุนไม่ขยับ ไม่ได้ค้าง · เวลาโหลดนับรวมใน
run_timeout_sec(7200 วินาที) · ถ้า % ไม่ขยับนานหลายนาที ให้ check network - ถ้าไม่มี tick จริงในช่วงนั้นเลย MT5 จะสร้าง tick จาก M1 เองโดยไม่เตือน แล้ว History Quality จะต่ำ (S2)
ระหว่าง run ดูเส้นทุนใน tab Graph ของ tester:
| เห็นอะไร | ทำอะไร |
|---|---|
| ลงต่อเนื่องหลายเดือน | หยุดได้ · กด Stop แล้วปิด MT5 ตัวนั้นด้วย ไม่งั้น queue รอจนครบ timeout |
| ขึ้นเรียบสวย | ห้ามอ่านว่าผ่าน — grid/martingale เป็นแบบนี้ก่อนพัง |
| แกว่ง หรือลงแล้วเด้ง | ห้ามปิด ปล่อยให้จบ |
lab นี้ไม่ต้องกด Stop — ต้องให้ run จนจบเพื่อมีรายงานใช้ในหัวข้อถัดไป
5 · file รายงาน · History Quality ก่อน
รายงานไปอยู่ใต้ backtest_root ของ config ตามโครงนี้:
<backtest_root>\<strategy>\<version>\<ชื่อบัญชี>\<preset>.htm
research\4-backtest\_lab\LAB_MACROSS_IS2026\LAB_MACROSS\V1.00\<ชื่อบัญชี>\default.htm
<ชื่อบัญชี> คือชื่อที่ตั้งตอนเพิ่มบัญชี demo (ใน clip คือ RoboMT5DemoECN) · preset default มาจากชื่อ file LAB_MACROSS_v1.00_default.set
ใน folder เดียวกันมีสาม file:
| file | คืออะไร |
|---|---|
default.htm |
รายงานของ tester |
default.ini |
ค่าที่ tester ใช้จริง |
default.log |
journal ของรอบนั้น |
ผลแปลกเมื่อไร เปิด .ini ก่อน ชื่อ file บอกแค่ว่าตั้งใจ run อะไร .ini บอกว่า run อะไรจริง ใน clip เปิดดูได้ Period=H1 · FromDate=2026.01.01 · ToDate=2026.04.30
เปิด default.htm ใน browser แล้วอ่านตามลำดับใน S5:
- History Quality ก่อนตัวเลขอื่น · ต่ำกว่า 90% = ทิ้งผลนั้น (รอบใน clip ได้ 99% real ticks)
- drawdown อ่านแถว Relative ไม่ใช่ Maximal
แล้วเปิด research\4-backtest\_lab\LAB_MACROSS_IS2026\summary.csv — ทุกงานใน config นี้รวมไว้แถวละงาน ดู column history_quality · total_trades · equity_dd_rel_pct
6 · mc: R · CI · DD จาก shuffle
bt\ea-bt.exe mc research\4-backtest\_lab\LAB_MACROSS_IS2026\LAB_MACROSS\V1.00\<ชื่อบัญชี>\default.htm --daily
mc แปลงแต่ละ trade เป็น R แล้วสลับลำดับ trade (shuffle) เพื่อดูว่า drawdown ลึกได้แค่ไหน · --daily ยุบ trade ในวันเดียวกันเป็นหนึ่งตัวอย่าง
บรรทัดที่ได้ใน clip:
days 24 · win 20.8% · E[R] -0.596 (bootstrap 95% -1.006..-0.138) · sd 1.09 · t -2.67 FAIL G4
อ่านแบบนี้:
- days 24 — มี 29 trade แต่กระจายอยู่ใน 24 วัน · trade ในวันเดียวกันไม่ใช่ตัวอย่างอิสระ n ที่ใช้จึงเป็นจำนวนวัน (S6)
- CI ทั้งช่วงอยู่ใต้ 0 (−1.006 ถึง −0.138) = ขาดทุนอย่างเป็นระบบ ไม่ใช่โชคไม่ดี · ถ้า CI คร่อม 0 แปลว่ายังบอกไม่ได้ว่ามี edge
- ป้าย
FAIL G4ท้ายบรรทัดเป็น gate ชุดเก่า ไม่ใช่เกณฑ์ S3 (S7) - แถว risk 1%: DD ลำดับจริง 15% · shuffle p50 14% · p95 16% — ลำดับที่เกิดจริงเป็นแค่เส้นทางเดียว ใช้ค่าหางจาก shuffle ตั้ง risk ไม่ใช่ค่าที่เกิดจริง
7 · verdict: เทียบกับเกณฑ์
bt\ea-bt.exe verdict research\4-backtest\_lab\LAB_MACROSS_IS2026\LAB_MACROSS\V1.00\<ชื่อบัญชี>
ผลใน clip: FAIL G2 — win% 20.69 ต่ำกว่า need% 39.05 · net −1,279.3 · t net −2.24
- need% คือ 1 / (1 + payoff) — win rate ขั้นต่ำที่ payoff ของ EA เองต้องการเพื่อคุ้มทุน ชนะต่ำกว่านี้ = แพ้โดยโครงสร้าง (เงื่อนไขเดียวกับ S6)
- ทำไม
mcขึ้น G4 แต่verdictขึ้น G2: verdict ตรวจ G2 (รูปทรง win/payoff) ก่อน G4 (net และ t) แล้วรายงานด่านแรกที่ตก verdictไม่ได้ตรวจครบ S1–S6 — ไม่ดู History Quality และไม่ตัดสินด้วย DD Relative หรือ CI รายวัน ใช้เป็นตัวช่วยอ่าน ไม่ใช่คำตัดสิน (รายละเอียดใน S7)
กลับไปกรอกคำตัดสินลงช่อง "ผล" ใน sidak-ledger.md
ถ้าผ่าน แปลว่า "น่าลงแรงต่อ" เท่านั้น ยังต้องผ่าน OOS และด่าน robustness R1–R6 (research\5-verdict\robustness.md) · R3 (slippage) วัดจากบัญชี demo ที่ forward เองได้ — ขั้นตอนอยู่ใน README.md ของ kit หัวข้อ "วัด slippage จากบัญชี demo ของตัวเอง"
8 · บันทึกสถานะ
เปิด research\status.yaml แก้แถว LAB_MACROSS:
| field | ค่า |
|---|---|
stage |
'5' |
state |
ตามคำตัดสิน (รอบใน clip = ตก) |
since |
วันที่ตัดสิน |
evidence |
research/4-backtest/_lab/LAB_MACROSS_IS2026/LAB_MACROSS/V1.00/<ชื่อบัญชี>/default.htm |
summary |
ประโยคเดียวที่คนไม่รู้ศัพท์อ่านเข้าใจ |
next |
งานถัดไป |
แล้ว run
bt\ea-bt.exe ea_status --check
ต้องไม่มี [error] · tab "สถานะกลยุทธ์" ใน dashboard อ่านจาก file นี้ ถ้าไม่แก้ dashboard จะยังขึ้นว่า EA อยู่ขั้น 3
ทำไมต้องแก้ทันที: ผ่านหรือตกด่านเมื่อไร แก้ในรอบเดียวกัน ถ้าเลื่อนไว้ก่อน สถานะใน file จะไม่ตรงกับความจริง และอีกไม่กี่สัปดาห์จะจำไม่ได้ว่า EA ตัวไหนตกเพราะอะไร
ค่าที่ได้ใน clip — run ของคุณเองควรได้ใกล้เคียง (bootstrap ขยับเล็กน้อยทุกครั้ง)
| ขั้น | ค่า |
|---|---|
| is_oos | 2026-01-01 → 2026-04-30 |
| เวลา | ดึง tick ม.ค.–เม.ย. 2026 ราว 3 นาที · run backtest 21 วินาที |
| History Quality | 99% real ticks |
| mc --daily | 29 trade · days 24 · win 20.8% · E[R] −0.596 [−1.006, −0.138] · t −2.67 |
| DD risk 1% | ลำดับจริง 15% · shuffle p50 14% · p95 16% |
| verdict | FAIL G2 · win% 20.69 < need% 39.05 · net −1,279.3 · t net −2.24 |
| คำตัดสิน | ตก — E[R] ≤ 0 และ win% ต่ำกว่าฐาน |
ถ้าคุณใช้ broker อื่นหรือ deposit ต่างจาก 10,000 ตัวเลขจะไม่ตรงกับตารางนี้ · ใน clip ใช้ deposit 1,000 (ดูหัวข้อ 1)
จุดที่มักพลาด
| พลาด | ผลที่ตามมา | ทางกัน |
|---|---|---|
พิมพ์ date_from / date_to เอง |
เลือกช่วงที่ถูกใจโดยไม่รู้ตัว | เอาจาก is_oos --year 2026 --yaml |
| ลด deposit เป็น 1,000 | lot เหลือ 0 หลังขาดทุน trade แรก EA หยุดยิงทั้งรอบ | ใช้ 10,000 ตาม config ของ kit |
| เขียนเกณฑ์หลังเห็นผล | เกณฑ์ถูกปรับให้ผ่าน | เขียนในหัว config และลง ledger ก่อนกด run |
| แก้ YAML หลังเข้า queue | งานยังใช้ config เดิม | เอางานออกแล้วเพิ่มใหม่ |
| กด Stop แต่ไม่ปิด MT5 | queue ค้างจนครบ run_timeout_sec |
ปิด MT5 ตัวนั้นด้วย |
| ไม่ได้ดึง tick ก่อน | MT5 สร้าง tick จาก M1 · History Quality ต่ำ | tick_depth --from 2026-01 ต้องตอบ yes |
อ่าน FAIL G4 / PASS ของ mc หรือ verdict เป็นคำตัดสิน S1–S6 |
ตัดสินด้วย gate ชุดเก่า | ไล่ S1–S6 ตาม S7 |
ลืมแก้ status.yaml |
dashboard แสดงสถานะผิด | แก้ทันทีแล้ว ea_status --check |