A1 · ออกแบบคำถามก่อนกด run
▶ clip: https://youtu.be/sY0aoBvmLkY
จบบทนี้แล้วทำได้:
- เขียน prereg ที่มีครบห้าข้อ และไม่มีช่องให้แก้ criteria หลังเห็นผล
- คำนวณว่าการทดสอบหลายครั้งเพิ่มโอกาส "ผ่านเพราะโชค" แค่ไหน และใช้ Šidák correction หาเส้น t ที่ต้องผ่าน
- ลงบรรทัดใน
sidak-ledger.mdตามกติกานับ k ที่ถูก - คำนวณจำนวน trade ขั้นต่ำด้วย
powerก่อนตัดสินใจว่าคำถามนั้นควร run หรือไม่
ต้องมีก่อน: จบ Standard แล้ว (สารบัญ Standard) โดยเฉพาะ P0 (prereg คืออะไร) · S2 (IS/OOS และ tick) · S6 (E[R] · CI · t) · ติดตั้ง kit แล้ว และมี Claude Code (plan Pro ขึ้นไป) สำหรับรอบ Advanced
1 · prereg คืออะไร และรอบ Advanced เพิ่มอะไร

prereg ย่อมาจาก pre-registration คือการ lock สามอย่างไว้ก่อนกด run: คำถาม · test period · criteria ที่เป็นตัวเลข ถ้าแก้ข้อใดข้อหนึ่งหลังเห็นผล ผลรอบนั้นใช้ตัดสินไม่ได้ เพราะเราจะเลือกอ่านไปทางที่ถูกใจได้เสมอ
ใน Standard เรียนแค่สามอย่างนั้น รอบ Advanced เพิ่มอีกสาม
| # | เพิ่มอะไร | ทำไมต้องมี |
|---|---|---|
| 1 | จำนวน trade ขั้นต่ำที่คำนวณจาก power | รู้ก่อน run ว่าข้อมูลพอแยก edge ออกจาก noise ไหม (หัวข้อ 4) |
| 2 | ตารางที่เขียนไว้ก่อนว่าผลแต่ละแบบนำไปสู่คำตัดสินอะไร | ผลที่ออกมาตีความได้ทางเดียว |
| 3 | นับ k ของ Šidák correction ทั้งกอง | ยิ่งทดสอบมาก ยิ่งต้องการ t สูงขึ้น (หัวข้อ 2–3) |
ตัวอย่างจริงในงานของผู้สอนคือรอบเลื่อนวัน (date-shift) criteria ได้รับอนุมัติก่อนผลออก และตารางตัดสินเขียนไว้ครบทุกแบบ ผลที่ออกมาจึงตีความได้ทางเดียว
ฝั่งขวาของ slide คือหัวข้อใน research\3-prereg\prereg-template.md ที่อยู่ใน kit ของคุณ เส้น "lock · จดเวลาอนุมัติ · แล้วค่อย run" แบ่ง file เป็นสองส่วน ข้อ 1–6 เขียนก่อน run ข้อ 7 (ผล) เขียนหลัง run และห้ามกลับไปแตะข้อ 1–6
แก้แผนกลางทางได้ แต่ต้องจดสามอย่าง: แก้อะไร · แก้เมื่อไร · แก้ก่อนหรือหลังเห็นผล ถ้าแก้หลังเห็นผล คนอ่านต้องรู้ เพื่อให้ลดน้ำหนักของผลนั้นได้
ข้อจำกัดที่ต้องรู้: prereg ไม่ได้ทำให้คำถามถูก criteria ที่หลวมก็ผ่านได้ถูกขั้นตอนเหมือนกัน prereg กันได้แค่การแก้เกณฑ์หลังเห็นผล ไม่ได้กันการตั้งเกณฑ์ที่อ่อนตั้งแต่ต้น
2 · prereg ห้าข้อ

prereg ที่ใช้ได้ต้องมีห้าข้อนี้
| ข้อ | เขียนอะไร | ได้มาจาก |
|---|---|---|
| 1 | คำถามข้อเดียว + ผลแบบไหนจะเปลี่ยนการตัดสินใจ | ตัวคุณเอง · ถ้าผลทุกแบบนำไปสู่การตัดสินใจเดิม ไม่ต้อง run |
| 2 | test period | bt\ea-bt.exe is_oos หลังจาก check tick ด้วย bt\ea-bt.exe tick_years --own แล้ว |
| 3 | criteria ผ่าน/ตก เป็นตัวเลข | แก้หลังเห็นผลไม่ได้ |
| 4 | บรรทัดใน ledger | นับ k ตามกติกาในหัวข้อ 3 |
| 5 | สิ่งที่รอบนี้ตอบไม่ได้ | เขียนไว้ก่อน run เช่น broker เดียว · era เดียว |
ห้าข้อนี้ map เข้ากับหัวข้อใน prereg-template.md ดังนี้: ข้อ 1 = หัวข้อ 1 · ข้อ 2 = หัวข้อ 2 · ข้อ 3 = หัวข้อ 3 (power) + 4 (criteria S1–S6) · ข้อ 4 = หัวข้อ 5 · ข้อ 5 = หัวข้อ 6 · หัวข้อ 4R (robustness R1–R6) ใช้หลังผ่านรอบแรก สอนใน A7
criteria ในหัว config นับเป็น prereg ได้ ถ้า commit ก่อน run เพราะ git จดเวลาไว้ให้ ใครก็ตรวจได้ว่าเกณฑ์อยู่ตรงนั้นก่อนรายงานจะเกิด
ตัวอย่างที่ไม่ควรทำตาม
แถวล่างของ slide คือโครง file prereg จริงของ EA-A: ที่มา → arm → Q1 สามทาง → Q2/Q3 → ข้อจำกัด → ผล
- Q1 สามทาง เขียนไว้ดี ผลแต่ละแบบมีคำตัดสินรออยู่แล้ว
- Q2 กับ Q3 เป็นคำบรรยาย ไม่ใช่ตัวเลข (กรอบเส้นประ) เมื่อผลออกมา คนเขียนเลือกได้ว่าจะอ่านว่าผ่านหรือตก นี่คือช่องที่ prereg มีไว้ปิด
case: criteria ที่ตั้งผิดไว้ก่อน run
criteria "อย่างน้อย 50 trade" ถูกตั้งผิดไว้ก่อน run แล้วเห็นผลแล้ว สิ่งที่ทำคือบอกตรง ๆ ว่าคู่นั้นอ่านเป็น criteria ไม่ได้ ไม่ใช่ย้อนกลับไปแก้ criteria ให้ผ่าน หัว template ก็เขียนไว้แบบเดียวกัน: "ถ้าพบว่า criteria ตั้งผิด ให้เขียนเพิ่มว่าผิดตรงไหน — ห้ามแก้ทับ"
3 · ทดสอบหลายครั้ง = เจอของปลอม

ทุกการทดสอบมีโอกาสผ่านเพราะโชคอยู่แล้ว ที่ alpha (α) 5% ทดสอบครั้งเดียวมีโอกาส 5% ทดสอบหลายครั้ง โอกาสได้ "ผ่าน" อย่างน้อยหนึ่งครั้งเพิ่มตามสูตร
โอกาสผ่านเพราะโชค = 1 − (1 − α)^k
| k (จำนวนการทดสอบ) | โอกาสผ่านเพราะโชคอย่างน้อยหนึ่งครั้ง (α = 5%) |
|---|---|
| 1 | 5% |
| 10 | 40% |
| หลักร้อย | เส้นแทบชนเพดาน 100% (ดูกราฟ) |
ทางแก้คือ Šidák correction ทำให้ α ต่อการทดสอบเล็กลงตาม k
α_k = 1 − (1 − 0.05)^(1/k)
α ที่เล็กลงแปลว่าเส้น t ที่ต้องผ่านสูงขึ้น กอง screening ของผู้สอนตอนนี้มี k = 306 เส้นที่ต้องผ่านจึงเป็น t ≥ 3.763 ไม่ใช่ 2
พูดง่าย ๆ: ถ้าคัด EA 300 ตัวแล้วหยิบตัวที่ดีที่สุดออกมา t = 2 ไม่ได้พิสูจน์อะไรเลย เพราะในกองขนาดนั้น EA ที่ไม่มี edge เลยก็จะมีบางตัวได้ t เกิน 2 ด้วยโชคล้วน ๆ
4 · กติกานับใน ledger

k มีความหมายก็ต่อเมื่อนับด้วยกติกาเดียวกันทุกครั้ง กติกานี้อยู่ในหัว research\3-prereg\sidak-ledger.md ของ kit
| นับเข้า k | ไม่นับ |
|---|---|
| arm ที่ได้ตัวเลขออกมา และมีสิทธิ์ถูกเลือก | arm ที่ถูกฆ่าก่อนมีรายงาน |
| control | |
| การทดสอบเพื่อวินิจฉัยกลไก (เช่น เลื่อนวัน · ยกราคา ใน A4) |
อีกสองข้อ
- คำถามเดียวที่ถามซ้ำข้ามปีหรือข้าม broker นับเป็น 1 เพราะเราไม่ได้เลือก "ปีที่ดีที่สุด" ออกมา เราดูว่าคำตอบเดียวกันไหม
- k ไม่ใช่เลขเดียวทั้ง repo สายงานใหม่ (EA ใหม่ที่ไม่เกี่ยวกับของเดิม) เริ่มนับใหม่ได้ แต่ต้องเขียนไว้ว่าเริ่มนับใหม่เพราะอะไร
ตารางขวาของ slide เป็นตัวอย่างสายงานเดียว (ไม่ใช่บรรทัดจริง): arm A, B, D ได้รายงานจึงนับ k = 1, 2, 3 และ α ที่ปรับเป็น 0.0500 · 0.0253 · 0.0170 ส่วน arm C ถูกฆ่าก่อนมีรายงาน k จึงค้างที่ 2
ledger ก็พลาดได้ เคยนับซ้ำตอนที่สองงานเพิ่มบรรทัดพร้อมกัน ถ้าทำหลายงานพร้อมกัน ให้เปิด file ดูบรรทัดล่าสุดก่อนเพิ่มเสมอ
⚠ ข้อที่ต้องระวังที่สุด: สายงานของ EA-A กับ EA-B ยังไม่เคยถูกนับย้อนหลัง คำว่า "ผ่าน" ที่เกิดก่อนมี ledger จึงยังไม่ได้แก้ปัญหาทดสอบหลายครั้ง
5 · power: ต้องใช้กี่ trade

ก่อน run ต้องรู้ว่าต้องมีกี่ trade ถึงจะแยก edge ออกจาก noise ได้
n ≈ 7.84 · (σ / δ)²
- δ = ขนาด edge ที่คาด หน่วยเป็น R ต่อ trade
- σ = sd ของผลต่อ trade หน่วย R (ค่าตั้งต้นของเครื่องมือคือ 1R)
| edge (δ) | trade ที่ต้องใช้ (σ = 1R) |
|---|---|
| 0.1R | ราว 800 (เครื่องมือคิดได้ 785) |
| 0.3R | ราว 88 |
δ อยู่ในตัวหารและยกกำลังสอง edge เล็กลงครึ่งหนึ่งจึงต้องใช้ trade เพิ่มสี่เท่า ดูจากกราฟจะเห็นว่าพอ edge ต่ำกว่า 0.1R จำนวน trade พุ่งขึ้นเป็นหลักพัน
ไอเดียที่มีแค่ 23 trade ไม่ควรเอาไป run เพราะผลออกมาแบบไหนก็สรุปอะไรไม่ได้ ถ้าบวกก็อาจเป็นโชค ถ้าลบก็อาจเป็นโชค เสียเวลา run และเสีย k ไปหนึ่ง
สูตรเดียวกันใช้คิดความยาวของ forward test ได้ เช่น EA-B ต้องมีราว 68 วันที่มี trade ซึ่งเท่ากับประมาณ 6 เดือน (หน่วยที่นับเป็นวันที่มี trade ไม่ใช่จำนวน trade ตามที่เรียนใน S6)
คำนวณก่อน run ด้วยคำสั่ง bt\ea-bt.exe power ใน Lab ข้างล่าง
Lab · เขียน prereg พร้อม power และบรรทัด ledger

เป้าหมาย: prereg หนึ่ง file ที่ผู้สอนหาช่องแก้ criteria หลังเห็นผลไม่เจอ
กติกา lab
- test period: Robo-Cen ปี 2016–2018 ซึ่งอยู่นอกตาราง IS/OOS · หรือช่วงข้อมูลที่ใช้ไปแล้วเท่านั้น
- ledger: เขียนใน
research\3-prereg\sidak-ledger.mdใน kit ของตัวเอง ห้ามแก้ ledger จริงของ repo ผู้สอน - lab นี้ไม่ต้องกด run backtest ส่งแค่ prereg
ขั้นที่ 1 · check tick ก่อน
bt\ea-bt.exe tick_years --own
output มีหนึ่งแถวต่อหนึ่ง terminal กับ symbol หัวตารางหน้าตาแบบนี้
terminal server symbol first last months full years (12 mo)
หาแถว terminal RoboForex ของคุณ แล้วดู column full years (12 mo) ว่าครอบปีที่จะใช้ไหม ถ้ายังไม่มีแถวไหนครอบ แปลว่า tick ยังไม่อยู่ในเครื่อง ดึงด้วย bt\ea-bt.exe tick_depth --terminal mt5\MT5_<ชื่อ> --from <เดือนแรก> ตาม kit README (ปิด MT5 ตัวนั้นก่อน) แล้ว run tick_years --own ใหม่ ถ้ายังไม่ครอบ ต้องหยุด ไม่ใช่ run ต่อ เพราะ MT5 จะปั้น tick จาก M1 ให้เงียบ ๆ (S5)
บัญชี demo อาจดึง tick ย้อนไปไม่ถึง 2016 (kit README วัด RoboForex-ECN demo ได้ถึง 2022-05 แล้วยังดึงต่อ) ถ้าไม่มี terminal ไหนครอบ 2016–2018 ให้ใช้ช่วงข้อมูลที่ใช้ไปแล้วแทน ซึ่งในขั้นที่ 2 is_oos --check จะบอกชื่อ block นั้นพร้อม exit 0 และใน prereg ต้องเขียนว่า "ช่วงข้อมูลที่ใช้ไปแล้ว"
*ต่อท้ายเดือนแรกใน columnfirstแปลว่า file เดือนนั้นเล็กกว่า 60% ของเดือนอื่น อาจดึงไม่ครบเดือน
ขั้นที่ 2 · ยืนยันว่าช่วงนี้อยู่นอกตาราง IS/OOS
bt\ea-bt.exe is_oos --check 2017-01-01 2017-06-30
ต้องเห็น
2017-01-01 .. 2017-06-30 → ★ matches no block — this range is neither IS nor OOS under the policy
พร้อม exit code 1 ใน lab นี้ exit 1 คือคำตอบที่ต้องการ เพราะช่วงนอกตารางไม่เผาครึ่ง OOS ของปีใด ห้ามจำตาราง IS/OOS เองหรือสุ่มใหม่ ถาม is_oos ทุกครั้ง
ขั้นที่ 3 · คำนวณ power
bt\ea-bt.exe power --edge 0.3
bt\ea-bt.exe power --edge 0.1
ที่ sd ตั้งต้น 1R ต้องได้
edge 0.300R (sd 1.00R) -> needs 88 trades
edge 0.100R (sd 1.00R) -> needs 785 trades

ขั้นที่ 2–3 บน kit จริง: power ให้ 88 trade ที่ 0.3R และ 785 trade ที่ 0.1R · is_oos --check ช่วง ม.ค.–มิ.ย. 2017 ขึ้น ★ matches no block แล้ว $LASTEXITCODE เป็น 1 (ภาพจัดหน้าจาก output ที่ capture ไว้)
ถ้ามีรายงานเก่าของ EA ตัวเดียวกัน เติม --from <รายงาน.htm> เพื่อดึง n กับ sd จริงมาแทนค่าตั้งต้น (option อื่น: --sd · --n · --per-year ดูด้วย bt\ea-bt.exe power --help)

ทางเดียวกันใน dashboard: tab เครื่องมือวิเคราะห์ › ก่อน run › ช่อง "ต้องมีกี่ trade ถึงจะตอบได้" เว้นช่อง file ว่างแล้วกด คำนวณ ได้ตารางทั้งชุด (sd 1.00R) — แถว 0.10 = 785 · แถว 0.30 = 88 ตรงกับคำสั่งข้างบน · บรรทัด $ python bt/power.py คือเครื่องมือตัวเดียวกับ ea-bt.exe power
ขั้นที่ 4 · เขียน prereg
copy research\3-prereg\prereg-template.md เป็น file ใหม่ (เช่น prereg-<ชื่อ>.md) แล้วเขียนให้ครบห้าข้อ: คำถาม · test period · criteria ตัวเลข · บรรทัด ledger · สิ่งที่ตอบไม่ได้
หมายเหตุ: ในหัวข้อ 2–3 ของ template คำสั่งยังเขียนเป็นแบบ
python bt/tick_years.pyใน kit ให้พิมพ์เป็นbt\ea-bt.exe tick_yearsแทน (เครื่องมือตัวเดียวกัน)
ขั้นที่ 5 · ลง ledger แล้ว commit ก่อน run
เพิ่มบรรทัดใน research\3-prereg\sidak-ledger.md (k สะสม · t ที่ต้องได้) แล้ว commit ทั้ง prereg และ ledger ขั้นนี้ไม่มีคำสั่งตรวจ ผู้สอนตรวจด้วยตา
ด่านผ่าน: criteria เป็นตัวเลขทุกข้อ · n ขั้นต่ำมาจาก power · มีบรรทัด ledger · commit ก่อน run
เฉลย — ทำเองก่อนแล้วค่อยเปิด
ไม่มีคำตอบเดียว เพราะคำถามของแต่ละคนต่างกัน สิ่งที่ผู้สอนตรวจ:
| ตรวจ | ผ่านเมื่อ | ตกเมื่อ |
|---|---|---|
| test period | อ้าง output tick_years ที่ครอบปีนั้น และ is_oos --check ขึ้น matches no block |
พิมพ์วันที่เองโดยไม่มี output อ้าง · ไม่ check tick |
| power | ระบุ δ ที่คาด และ n จาก power (88 ที่ 0.3R · 785 ที่ 0.1R หรือค่าจาก --from) |
ไม่มี n ขั้นต่ำ หรือ n ขั้นต่ำเกินจำนวน trade ที่ test period นั้นให้ได้แต่ยัง run ต่อ |
| criteria | ทุกข้อมีตัวเลขและทิศ (≥ · > · ≤) เช่น S1 history_quality ≥ 90% · S5 Equity DD Relative ≤ 30% |
มีข้อที่เป็นคำบรรยาย เช่น "ผลดูดี" · "DD ไม่สูงเกินไป" (แบบ Q2/Q3 ในหัวข้อ 2) |
| ledger | k สะสมกับ t ที่ต้องได้ ตรงกับเส้น Šidák ของทีม (ตารางในหัว bt/verdict.py: k = 1 → 2.00 · 10 → 2.80 · 20 → 3.02 · 50 → 3.28 · 100 → 3.47) |
ไม่มีบรรทัด หรือนับ arm ที่ไม่ควรนับ |
| สิ่งที่ตอบไม่ได้ | อย่างน้อย broker เดียว / era เดียว ถ้าเป็นแบบนั้นจริง | เว้นว่าง |
| เวลา | commit ของ prereg + ledger เกิดก่อนรายงานใด ๆ | commit พร้อมหรือหลังรายงาน |
จุดที่มักพลาด
| พลาด | ผลที่ตามมา | ทางกัน |
|---|---|---|
| เขียน criteria เป็นคำบรรยาย | ผลออกมาแล้วเลือกอ่านทางที่ถูกใจได้ | ทุกข้อต้องเป็นตัวเลขพร้อมทิศ |
| จำตาราง IS/OOS เอง หรือสุ่มใหม่ | เผาครึ่ง OOS โดยไม่รู้ตัว หรือเลือกหน้าต่างที่ถูกใจ | ถาม is_oos ทุกครั้ง |
| ไม่ check tick ก่อน | MT5 ปั้น tick จาก M1 ให้เงียบ ๆ ผลไม่มีความหมาย | tick_years --own ก่อนตั้ง test period |
| แก้ criteria ที่ตั้งผิดให้ผ่าน | prereg ไม่มีความหมาย | เขียนเพิ่มว่าผิดตรงไหน บอกว่าคู่นั้นอ่านเป็น criteria ไม่ได้ |
| ใช้เส้น t = 2 กับกองใหญ่ | หยิบตัวที่ผ่านเพราะโชคออกมา | ใช้เส้นจาก Šidák ตาม k ใน ledger |
| นับ arm ที่ถูกฆ่า / control / การวินิจฉัย เข้า k | เส้น t เข้มเกินจริง ตัดตัวที่ดีทิ้ง | นับเฉพาะ arm ที่ได้ตัวเลขและมีสิทธิ์ถูกเลือก |
| run ไอเดียที่ได้ trade น้อยกว่า power | ผลแบบไหนก็สรุปไม่ได้ เสีย k ไปเปล่า ๆ | power ก่อน run |
ทวนท้ายบท

- ทดสอบ 10 ครั้งที่ α = 5% โอกาสได้ "ผ่าน" เพราะโชคอย่างน้อยหนึ่งครั้งเท่าไร แก้ด้วยอะไร
- arm แบบไหนนับเข้า k ใน ledger แบบไหนไม่นับ
- criteria "≥ 50 trade" ตั้งผิดไว้ก่อน run และเห็นผลแล้ว ต้องทำอย่างไร
เฉลย
- ราว 40% จาก 1 − (1 − α)^k = 1 − 0.95¹⁰ แก้ด้วย Šidák correction ที่ทำให้ α ต่อการทดสอบเล็กลงตาม k
- นับ arm ที่ได้ตัวเลขและมีสิทธิ์ถูกเลือก · ไม่นับ arm ที่ถูกฆ่าก่อนมีรายงาน · control · การทดสอบวินิจฉัยกลไก
- ห้ามแก้ criteria บอกตรง ๆ ว่าคู่นั้นอ่านเป็น criteria ไม่ได้ ถ้าจะแก้แผน ต้องจดว่าแก้อะไร เมื่อไร ก่อนหรือหลังเห็นผล