Parameter Optimization & Overfitting
ในบทที่แล้ว เราใช้ EMA 20/200 กับ SPY แล้วได้ผลตอบแทนสะสม 367.41% ในช่วง 20 ปี คำถามถัดมาคือ ถ้าเปลี่ยน 20 กับ 200 เป็นตัวเลขอื่น ผลจะดีขึ้นไหม บทนี้จะลองทุกคู่ที่เป็นไปได้ในช่วงหนึ่ง หาคู่ที่ดีที่สุด แล้วตรวจว่าคู่ที่ "ดีที่สุด" นั้นดีจริง หรือแค่เข้ากับข้อมูลชุดที่เราใช้หาพอดี
ทำไมต้องเป็น 20 กับ 200
ตัวเลข 20 และ 200 ไม่ได้มาจากสูตร เราเลือกเพราะคนนิยมใช้ ถ้าเปลี่ยนเป็น 25/180 หรือ 65/120 กลยุทธ์ก็ยังเป็น EMA สั้นตัดยาวเหมือนเดิม ต่างกันแค่ความเร็วในการตอบสนองต่อราคา
ตัวเลขที่เราตั้งเองแบบนี้เรียกว่า parameter การปรับหา parameter ที่ทำให้ตัวชี้วัดที่เราเลือกออกมาดีที่สุดเรียกว่า Parameter Optimization วิธีที่ตรงที่สุดคือลองทุกคู่ในตาราง (grid search หรือ brute force) หนังสือ Python for Algorithmic Trading ของ Yves Hilpisch ทำแบบเดียวกันกับ SMA บน EUR/USD ปี 2010–2019 โดยให้ optimize_parameters ไล่ SMA เร็ว 30–50 กับ SMA ช้า 200–300 แล้วได้คู่ 48/238 (หน้า PDF 87–88)
เขียนเป็นสมการได้ว่า เราเลือกคู่ (nf∗,ns∗)(n_f^*, n_s^*) ที่ทำให้ Sharpe สูงที่สุดใน grid GG
(nf∗,ns∗)=argmax(nf, ns)∈GSharpe(nf,ns),Sharpe=rˉsr252(n_f^*, n_s^*) = \arg\max_{(n_f,\,n_s) \in G} \text{Sharpe}(n_f, n_s), \qquad \text{Sharpe} = \frac{\bar r}{s_r}\sqrt{252}nfn_f คือจำนวนวันของ EMA เร็ว nsn_s คือจำนวนวันของ EMA ช้า rˉ\bar r กับ srs_r คือค่าเฉลี่ยและส่วนเบี่ยงเบนมาตรฐานของผลตอบแทนรายวันหลังค่าธรรมเนียม บทนี้ใช้อัตราปลอดความเสี่ยง 0% เหมือนบทที่ 4
Parameter Optimization: ลองทุกคู่
เราใช้ข้อมูลและกติกาชุดเดียวกับบทที่ 4 ทุกอย่าง คือราคา SPY รายวันจาก Webull OpenAPI ถือ SPY 100% เมื่อ EMA เร็วอยู่เหนือ EMA ช้าที่ราคาปิดวันก่อน ซื้อขายที่ราคาเปิดวันถัดไป และเสียค่าธรรมเนียมสมมติ 0.1% ต่อข้าง สิ่งเดียวที่เปลี่ยนคือคู่ EMA
| สิ่งที่ลอง | ค่า |
|---|---|
| EMA เร็ว | 5, 10, 15, …, 100 วัน (20 ค่า) |
| EMA ช้า | 50, 60, 70, …, 300 วัน (26 ค่า) |
| เงื่อนไข | EMA เร็วต้องสั้นกว่า EMA ช้า |
| จำนวนคู่ที่ทดสอบ | 484 คู่ |
| ตัวชี้วัดที่ใช้เลือก | Sharpe รายวัน × √252 |
โค้ดในไฟล์ lesson_15.py ทำแค่วนลูปเรียก backtest ของบทที่ 4 ทีละคู่
from lesson_15 import load_bars, run_grid, EVALUATION bars = load_bars() # SPY รายวันจาก Webull ที่ดึงไว้แล้วresults = run_grid(bars, EVALUATION) # 484 คู่ ช่วง 2006-09-26 ถึง 2026-09-25best = max(results, key=lambda r: r['sharpe'])print(best['fast'], best['slow'], round(best['sharpe'], 2)) # 5 90 0.84เมื่อมองย้อนหลังทั้ง 20 ปี คู่ที่ดีที่สุดคือ EMA 5/90 ได้ Sharpe 0.84 และ CAGR 9.49% ขาดทุนหนักสุด (Max DD) −19.01% ส่วน EMA 20/200 ได้ Sharpe 0.66 อยู่อันดับ 237 จาก 484 คู่ ตรงกลางตารางพอดี ถ้าเราเอา 5/90 ไปโชว์ ตัวเลขจะดูดีกว่าบทที่แล้วมาก แต่เราได้ 5/90 มาจากการเห็นราคาทั้ง 20 ปีก่อนแล้วค่อยเลือก ซึ่งในวันที่เริ่มเทรดจริงเราไม่มีข้อมูลนั้น
ลองทุกคู่ EMA แล้วดูว่าคู่ไหนเด่น
แต่ละช่องคือกลยุทธ์ EMA หนึ่งคู่ แกนนอนคือ EMA ช้า แกนตั้งคือ EMA เร็ว ช่องสีเข้มคือค่าที่สูงกว่าในช่วงที่เลือก ลองสลับช่วงเวลาแล้วสังเกตว่าบริเวณสีเข้มย้ายไปไหน
- EMA 20/200 จากบทที่ 4
- EMA 65/120 ดีที่สุดในช่วงฝึก
- ดีที่สุดในมุมมองนี้ (5/90)
- คู่ที่เลือก
- EMA 20/200อันดับ 237 จาก 484 ตาม Sharpe
- Sharpe
- 0.662006–2026
- CAGR
- 8.02%ต่อปี
- Max DD
- -26.7%17 เทรดที่ปิดแล้ว
ช่องว่างมุมซ้ายบนคือคู่ที่ EMA เร็วยาวเท่าหรือยาวกว่า EMA ช้า ซึ่งไม่ได้ทดสอบ · สีคำนวณใหม่ตามค่าต่ำสุดถึงสูงสุดของมุมมองที่เลือก · ค่าธรรมเนียม 0.1% ต่อข้าง · Sharpe ใช้อัตราปลอดความเสี่ยง 0%
ลองกดสลับระหว่าง "ช่วงฝึก 2006–2016" กับ "ช่วงทดสอบ 2016–2026" แล้วดูบริเวณสีเข้ม ในช่วงแรก สีเข้มกองอยู่แถว EMA เร็ว 55–90 คู่กับ EMA ช้า 80–130 พอเปลี่ยนเป็นช่วงหลัง สีเข้มย้ายไปอยู่ที่ EMA เร็วสั้น ๆ 10–25 วัน คู่ที่เด่นในสิบปีหนึ่งไม่ได้เด่นในอีกสิบปี
Overfitting: จำอดีตแทนที่จะเรียนรู้
Hilpisch ยกนิยามของ Man Institute ว่า overfitting คือการที่แบบจำลองอธิบาย noise แทนที่จะอธิบาย signal ผลในข้อมูลที่ใช้ทดสอบจึงดี แต่ทำนายข้อมูลใหม่ได้น้อยหรือไม่ได้เลย (หน้า PDF 100) EMA มีแค่สองตัวเลขก็ overfit ได้ เพราะเราลอง 484 คู่แล้วเก็บคู่ที่ออกมาดีที่สุด ยิ่งลองมาก ก็ยิ่งมีโอกาสเจอคู่ที่บังเอิญเข้ากับเหตุการณ์ในอดีตพอดี
อีกคำที่มาคู่กันคือ data snooping Hilpisch อ้าง White (2000) ว่าเกิดขึ้นเมื่อเราใช้ข้อมูลชุดเดียวกันมากกว่าหนึ่งครั้งเพื่อสรุปผลหรือเลือกแบบจำลอง Grid search บนข้อมูล 20 ปีชุดเดียวคือการใช้ข้อมูลชุดเดิมซ้ำ 484 ครั้ง
แบ่งข้อมูลเป็นช่วงฝึกกับช่วงทดสอบ
วิธีพื้นฐานที่สุดในการจับ overfitting คือแบ่งข้อมูลก่อนเริ่ม optimize ส่วนแรกเรียกว่า In-sample หรือช่วงฝึก ใช้หาพารามิเตอร์ ส่วนหลังเรียกว่า Out-of-sample หรือช่วงทดสอบ เก็บไว้โดยไม่ดูจนกว่าจะเลือกเสร็จ Hilpisch ใช้การแบ่งแบบนี้กับกลยุทธ์ regression และเขียนไว้ว่ากลยุทธ์ที่มีขั้นตอน optimize หรือ fit ควรประเมินแบบนี้ เพราะช่วยลดปัญหา data snooping และ overfitting (หน้า PDF 118)
บทนี้แบ่ง 20 ปีออกเป็นสองท่อนเท่ากัน
| ช่วง | วันที่ | วันซื้อขาย | ใช้ทำอะไร |
|---|---|---|---|
| ช่วงฝึก (In-sample) | 2006-09-26 ถึง 2016-09-23 | 2,517 | ลอง 484 คู่ แล้วเลือกคู่ที่ Sharpe สูงสุด |
| ช่วงทดสอบ (Out-of-sample) | 2016-09-26 ถึง 2026-09-25 | 2,514 | นำคู่ที่เลือกแล้วมารันครั้งเดียว ห้ามกลับไปเลือกใหม่ |
แต่ละช่วงเริ่มบัญชีใหม่ด้วยเงินสด 100,000 USD ส่วน EMA คำนวณต่อเนื่องจากราคาก่อนหน้า เส้น EMA วันแรกของช่วงทดสอบจึงใช้ราคาในอดีตได้ตามปกติ เพราะราคาเหล่านั้นเกิดขึ้นแล้วจริง
ในช่วงฝึก คู่ที่ชนะคือ EMA 65/120 ได้ Sharpe 0.72 CAGR 8.59% และ Max DD −17.31% ส่วนการซื้อแล้วถือ SPY ในช่วงเดียวกันได้ Sharpe 0.44 และ Max DD −55.19% เพราะช่วงนี้มีวิกฤตปี 2008 EMA 65/120 ออกจากตลาดได้ก่อนช่วงที่ร่วงหนัก ถ้าหยุดดูแค่ตรงนี้ เราจะสรุปว่าเจอกลยุทธ์ที่ทั้งกำไรมากกว่าและเสี่ยงน้อยกว่าตลาด
EMA 65/120 ชนะในช่วงฝึก แล้วช่วงทดสอบเป็นอย่างไร
เส้นม่วงคือคู่ที่ Sharpe ช่วงฝึกสูงสุด เราเลือกมันโดยไม่ได้เห็นข้อมูลหลังเดือนกันยายน 2016 ปุ่ม "เริ่มนับใหม่" ตั้งทุกเส้นเป็น 100 ในวันแรกของช่วงทดสอบ เพื่อเทียบเฉพาะส่วนที่ยังไม่เคยเห็น
- EMA 65/120
- EMA 20/200
- ซื้อแล้วถือ SPY
มูลค่าพอร์ต เริ่ม 100 ที่ 2016-09-26 · สเกล log
100200400201620182020202220242026- วันที่
- 2026-09-25
- EMA 65/120
- 270.0
- EMA 20/200
- 282.7
- ซื้อแล้วถือ SPY
- 420.3
| กลยุทธ์ | Sharpe | CAGR | Max DD | เทรด |
|---|---|---|---|---|
| EMA 65/120 | 0.77 | 10.42% | -29.4% | 6 |
| EMA 20/200 | 0.83 | 10.93% | -26.7% | 7 |
| ซื้อแล้วถือ SPY | 0.89 | 15.42% | -33.7% | — |
ราคา SPY รายวันจาก Webull OpenAPI ดึงเมื่อ 2026-09-28 · ราคาปรับย้อนหลังแล้ว ปันผลอยู่ในราคา · ค่าธรรมเนียมสมมติ 0.1% ต่อข้าง ไม่รวม spread slippage และภาษี · แถบสีเทาคือช่วงฝึก
พอนำ EMA 65/120 ไปรันในช่วงทดสอบ ผลออกมาดังนี้
| ช่วงทดสอบ 2016–2026 | Sharpe | CAGR | Max DD | อันดับ Sharpe จาก 484 คู่ |
|---|---|---|---|---|
| EMA 65/120 (ชนะช่วงฝึก) | 0.77 | 10.42% | −29.36% | 197 |
| EMA 20/200 (ค่าที่ใช้ในบทที่ 4) | 0.83 | 10.93% | −26.67% | 101 |
| ซื้อแล้วถือ SPY | 0.89 | 15.42% | −33.72% | — |
Sharpe ของ EMA 65/120 ในช่วงทดสอบ (0.77) สูงกว่าในช่วงฝึก (0.72) เสียอีก ตัวเลขนี้หลอกตาได้ง่าย เพราะสิบปีหลังเป็นตลาดขาขึ้นเกือบตลอด 475 จาก 484 คู่ได้ Sharpe ในช่วงทดสอบสูงกว่าช่วงฝึก ค่ามัธยฐานของทั้ง 484 คู่ขยับจาก 0.57 ในช่วงฝึกเป็น 0.74 ในช่วงทดสอบ เวลาอ่านผลช่วงทดสอบ ให้เทียบกับทางเลือกอื่นในช่วงเวลาเดียวกัน อย่าเทียบกับตัวเลขของตัวเองในช่วงฝึก
เมื่อเทียบแบบนั้น คู่ที่ชนะช่วงฝึกตกไปอยู่อันดับ 197 แพ้ EMA 20/200 ที่เราไม่ได้ optimize เลย และแพ้การซื้อแล้วถือทั้ง Sharpe และ CAGR ข้อได้เปรียบที่เห็นในช่วงฝึกมาจากการหลบปี 2008 ได้ พอไม่มีวิกฤตแบบเดิม ข้อได้เปรียบนั้นก็หายไป
อันดับที่ไม่ข้ามช่วงเวลา
ถ้าการ optimize ได้ผลจริง คู่ที่อยู่อันดับต้นในช่วงฝึกควรอยู่อันดับต้นในช่วงทดสอบด้วย เราวัดเรื่องนี้ได้ด้วย Spearman rank correlation ซึ่งเทียบอันดับของสองชุด ค่า 1 แปลว่าอันดับเหมือนกันทุกตำแหน่ง ค่า 0 แปลว่าไม่สัมพันธ์กัน และค่าติดลบแปลว่าอันดับกลับทิศ
ρ=corr(rank(SharpeIS), rank(SharpeOOS))\rho = \operatorname{corr}\big(\operatorname{rank}(\text{Sharpe}_{\text{IS}}),\ \operatorname{rank}(\text{Sharpe}_{\text{OOS}})\big)สำหรับ 484 คู่ในบทนี้ ρ=−0.09\rho = -0.09 รู้อันดับในช่วงฝึกแล้วก็เดาอันดับในช่วงทดสอบแทบไม่ได้
อันดับในช่วงฝึก ข้ามไปช่วงทดสอบได้ไหม
จุดหนึ่งจุดคือคู่ EMA หนึ่งคู่ แกนนอนคือ Sharpe ช่วงฝึก 2006–2016 แกนตั้งคือ Sharpe ของคู่เดียวกันในช่วงทดสอบ 2016–2026 ถ้าคู่ที่เก่งในช่วงฝึกยังเก่งต่อ จุดสีม่วงจะไปกองอยู่มุมขวาบน
- 10 คู่ที่ Sharpe ช่วงฝึกสูงสุด
- EMA 20/200
- คู่อื่น
- คู่ที่เลือก
- EMA 65/120
- ช่วงฝึก
- 0.72อันดับ 1 จาก 484
- ช่วงทดสอบ
- 0.77อันดับ 197 จาก 484
- Rank correlation
- -0.09ทั้ง 484 คู่
Rank correlation (Spearman) ใกล้ 0 แปลว่ารู้อันดับในช่วงฝึกแล้วเดาอันดับในช่วงทดสอบแทบไม่ได้ · เส้นประคือ Sharpe ของการซื้อแล้วถือ SPY ในแต่ละช่วง · ช่วงทดสอบทั้งช่วงเป็นตลาดขาขึ้น จึงทำให้คู่ส่วนใหญ่ได้ Sharpe สูงขึ้นพร้อมกัน
ลองเลือกคู่จาก 10 อันดับแรกของช่วงฝึกทีละคู่ อันดับในช่วงทดสอบกระจายตั้งแต่ 23 ถึง 436 คู่ที่ดีที่สุดในช่วงทดสอบคือ EMA 10/110 ได้ Sharpe 1.08 แต่ในช่วงฝึกมันอยู่อันดับ 315 ส่วน EMA 20/200 อยู่อันดับ 439 ในช่วงฝึก ก่อนขึ้นมาอันดับ 101 ในช่วงทดสอบ
บางคนแนะนำให้เลือกคู่ที่อยู่กลาง "ที่ราบ" ซึ่งคู่ข้างเคียงก็ได้ผลดีใกล้กัน แทนการเลือกยอดแหลมที่ดีอยู่คู่เดียว เราลองแล้วด้วยการเฉลี่ย Sharpe ของแต่ละคู่กับคู่ข้างเคียงรอบตัวในช่วงฝึก คู่ที่ได้คะแนนเฉลี่ยสูงสุดคือ EMA 70/110 แต่ในช่วงทดสอบมันอยู่อันดับ 386 ในข้อมูลชุดนี้ การเลือกที่ราบช่วยไม่ได้ เพราะทั้งที่ราบย้ายที่ไปพร้อมกับสภาพตลาด
ลองกับตลาดที่ไม่มีสัญญาณ
ถ้าเรายังไม่แน่ใจว่าผลดีในช่วงฝึกมาจากความบังเอิญได้มากขนาดไหน วิธีหนึ่งคือสร้างตลาดที่เรารู้แน่ว่าไม่มีแนวโน้มให้ EMA จับได้ แล้วทำ optimization แบบเดิม
เราสุ่มหยิบผลตอบแทนรายวันของ SPY ช่วง 2006–2026 มาเรียงใหม่แบบใส่คืน (bootstrap) สร้างเป็นโลกสมมติ 60 โลก โลกละ 2,520 วัน ขนาดการขึ้นลงรายวันยังเหมือน SPY แต่ลำดับเวลาถูกทำลาย แนวโน้มที่ EMA ใช้จึงไม่มีอยู่จริง ในแต่ละโลก เราแบ่งครึ่งแรกเป็นช่วงฝึก ครึ่งหลังเป็นช่วงทดสอบ แล้วลองเลือกคู่ที่ดีที่สุดจาก N คู่
ลองมากขึ้น ผลย้อนหลังยิ่งดูดี ทั้งที่ตลาดไม่มีสัญญาณ
เราสุ่มผลตอบแทนรายวันของ SPY มาเรียงใหม่ 60 โลก โลกละ 2,520 วัน ลำดับเวลาถูกทำลาย EMA จึงไม่มีแนวโน้มจริงให้จับ ในแต่ละโลก เราลอง N คู่ เลือกคู่ที่ Sharpe ครึ่งแรกดีที่สุด แล้วอ่านผลครึ่งหลัง
- Sharpe ครึ่งแรก (ใช้เลือก)
- 0.57เฉลี่ย 60 โลก
- Sharpe ครึ่งหลัง (ไม่เคยเห็น)
- 0.36เฉลี่ย 60 โลก
- ส่วนต่าง
- 0.2137 จาก 60 โลก ครึ่งหลังแย่กว่า
เส้นทึบคือค่าเฉลี่ย แถบจางคือช่วงครึ่งกลางของโลกทั้งหมด (เปอร์เซ็นไทล์ 25–75) · bootstrap ผลตอบแทนรายวัน SPY 2006–2026 แบบใส่คืน seed 20260929 · ราคาเปิดเท่ากับราคาปิดวันก่อน · ค่าธรรมเนียม 0.1% ทุกครั้งที่เปลี่ยนสถานะ · Sharpe ของครึ่งหลังที่ยังบวกมาจาก drift ของ SPY ที่ติดมากับผลตอบแทนที่สุ่ม
เมื่อลองคู่เดียว Sharpe ช่วงฝึกกับช่วงทดสอบใกล้กัน (0.30 กับ 0.31) เพราะไม่มีการเลือก พอเพิ่มเป็นการเลือกจากทั้ง 74 คู่ Sharpe ช่วงฝึกของคู่ที่ชนะเฉลี่ยขึ้นไปถึง 0.57 แต่ช่วงทดสอบอยู่ที่ 0.36 เท่านั้น ส่วนต่าง 0.21 นี้มาจากการเลือกล้วน ๆ เพราะโลกนี้ไม่มีสัญญาณให้เลือก Sharpe ช่วงทดสอบที่ยังเป็นบวกมาจากผลตอบแทนเฉลี่ยของ SPY ที่ติดมากับข้อมูลที่สุ่ม ไม่ได้มาจาก EMA
ผลนี้ใช้อ่านผลกับ SPY จริงได้ด้วย ในช่วงฝึกเราลองไป 484 คู่ มากกว่าในโลกสมมติราวหกเท่าครึ่ง Sharpe 0.72 ของ EMA 65/120 จึงรวมส่วนที่ได้จากการเลือกไว้ด้วย ตัวเลขที่ควรรายงานคู่กับผล optimize จึงมีจำนวนคู่ที่ลองไปด้วย Hilpisch อ้างงานของ Bailey et al. (2015) ไว้ว่า การลองพารามิเตอร์จำนวนมากบนข้อมูลการเงินที่ signal-to-noise ต่ำ มักได้พารามิเตอร์ที่เข้ากับ noise ในอดีต (หน้า PDF 100)
Walk-forward: เลือกใหม่ทุกปี
การแบ่งครั้งเดียวให้ช่วงทดสอบแค่ช่วงเดียว ผลจึงขึ้นกับว่าเราตัดตรงไหน ถ้าตัดปี 2011 แทน 2016 เรื่องราวอาจเปลี่ยน Walk-forward แก้เรื่องนี้ด้วยการเลื่อนหน้าต่างไปตามเวลา ซึ่งเป็นแบบ Historical ที่เราพูดถึงในบท Introduction of Backtest
กติกาในบทนี้คือ ทุกวันที่ 26 กันยายน ตั้งแต่ปี 2011 ถึง 2025 ให้ดู Sharpe ของทั้ง 484 คู่ในห้าปีก่อนหน้า เลือกคู่ที่ดีที่สุด แล้วใช้คู่นั้นเทรดไปหนึ่งปี ปีถัดไปก็เลือกใหม่ รวมเป็น 15 ปีทดสอบที่ไม่มีปีไหนเคยถูกใช้เลือกพารามิเตอร์ของตัวเอง
เลือกคู่ใหม่ทุกปี จากข้อมูล 5 ปีก่อนหน้า
ทุกวันที่ 26 กันยายน เราดู Sharpe ของทั้ง 484 คู่ในห้าปีก่อนหน้า เลือกคู่ที่ดีที่สุด แล้วใช้คู่นั้นเทรดไปหนึ่งปี กดแต่ละปีเพื่อดูว่าคู่ที่ถูกเลือกเปลี่ยนไปอย่างไร
- 201110/508.2%
- 201210/5013.8%
- 201310/5011.7%
- 201455/2400.8%
- 201555/80-0.3%
- 2016100/27017.6%
- 20175/27018.9%
- 20185/270-5.7%
- 20195/3005.0%
- 20205/16036.9%
- 202110/110-10.3%
- 202210/1103.8%
- 202310/11028.2%
- 202410/11012.3%
- 202540/1108.6%
ปีทดสอบ 2011-09-26 ถึง 2012-09-25: ฝึกด้วยข้อมูล 2006-09-26 ถึงวันก่อนเริ่มปี เลือก EMA 10/50 (Sharpe ช่วงฝึก 0.76) ปีถัดมาพอร์ตเปลี่ยนไป 8.19%
- Walk-forward
- EMA 20/200 คงที่
- ซื้อแล้วถือ SPY
มูลค่าพอร์ต พันดอลลาร์ เริ่ม 100 ที่ 2011-09-26 · สเกล log
10020040080020122014201620182020202220242026- วันที่
- 2026-09-25
- Walk-forward
- 381.2
- EMA 20/200 คงที่
- 428.8
- ซื้อแล้วถือ SPY
- 872.2
| วิธี | Sharpe | CAGR | Max DD | เทรด |
|---|---|---|---|---|
| Walk-forward | 0.78 | 9.33% | -22.5% | 24 |
| EMA 20/200 คงที่ | 0.81 | 10.19% | -26.7% | 10 |
| ซื้อแล้วถือ SPY | 0.95 | 15.54% | -33.7% | — |
คะแนนช่วงฝึกใช้ผลตอบแทนรายวันของแต่ละคู่ที่รันต่อเนื่อง · พอร์ต walk-forward เป็นบัญชีเดียว เปลี่ยนคู่ได้เฉพาะวันเริ่มปีทดสอบ และเสียค่าธรรมเนียมเมื่อสถานะเปลี่ยน · ผลรายปีคือการเปลี่ยนแปลงของมูลค่าพอร์ตในปีนั้น
ใน 15 ปี คู่ที่ถูกเลือกเปลี่ยนไป 9 แบบ เริ่มจาก 10/50 ข้ามไป 55/240 และ 55/80 แล้วเป็น 100/270 ต่อด้วย 5/270 จากนั้นกลับมาอยู่ที่ 10/110 สี่ปีติด ถ้าพารามิเตอร์ที่ดีที่สุดมีอยู่จริงและคงที่ เราน่าจะเห็นคู่เดิมหรือคู่ใกล้กันถูกเลือกซ้ำ การที่คำตอบกระโดดไปมาแบบนี้บอกว่าแต่ละรอบ optimization จับลักษณะของห้าปีที่ผ่านมามากกว่าจับกลไกที่ใช้ได้ต่อ
| 2011-09-26 ถึง 2026-09-25 | Sharpe | CAGR | Max DD | เทรด |
|---|---|---|---|---|
| Walk-forward เลือกใหม่ทุกปี | 0.78 | 9.33% | −22.46% | 24 |
| EMA 20/200 คงที่ | 0.81 | 10.19% | −26.67% | 10 |
| ซื้อแล้วถือ SPY | 0.95 | 15.54% | −33.72% | — |
Walk-forward ขาดทุนหนักสุดน้อยกว่า EMA 20/200 แต่ Sharpe และ CAGR ต่ำกว่า และเทรดบ่อยกว่าเกินสองเท่า การ optimize ใหม่ทุกปีจึงไม่ได้ให้ผลดีกว่าการใช้คู่คงที่ที่เลือกมาโดยไม่ดูข้อมูลเลย ข้อดีของ walk-forward อยู่ที่ตัวเลขในตารางเป็นผลที่ทำได้จริง ณ เวลานั้น ทุกปีทดสอบใช้พารามิเตอร์ที่เลือกจากข้อมูลก่อนหน้าเท่านั้น จึงบอกเราได้ตรงกว่าตัวเลข 5/90 ที่เลือกหลังเห็นครบ 20 ปี
ก่อนเชื่อพารามิเตอร์ที่ดีที่สุด
ตัวเลขที่ได้จากการ optimize ต้องอ่านคู่กับวิธีที่ได้มันมา ก่อนเชื่อพารามิเตอร์ชุดไหน ให้ตรวจสิ่งเหล่านี้
- แบ่งข้อมูลก่อนเริ่ม กำหนดช่วงฝึก ช่วงทดสอบ ขอบเขตของ grid และตัวชี้วัดที่ใช้เลือกไว้ล่วงหน้า แล้วเขียนเก็บไว้ ถ้าเปิดดูช่วงทดสอบแล้วกลับไปแก้ grid ช่วงทดสอบนั้นก็กลายเป็นส่วนหนึ่งของการฝึกไปแล้ว
- รายงานจำนวนครั้งที่ลอง Sharpe 0.72 ที่ได้จากการเลือกจาก 484 คู่ มีความหมายต่างจาก Sharpe 0.72 ของกฎที่คิดไว้ก่อนแล้วรันครั้งเดียว
- เทียบกับทางเลือกที่ไม่ต้อง optimize ในบทนี้คือ EMA 20/200 และการซื้อแล้วถือ SPY ในช่วงเวลาเดียวกัน ถ้าคู่ที่ optimize แล้วยังแพ้สองทางเลือกนี้ในช่วงทดสอบ การ optimize ก็ไม่ได้เพิ่มอะไรให้
- ดูอันดับ ไม่ใช่แค่ระดับ ตลาดขาขึ้นทำให้ Sharpe ของทุกคู่สูงขึ้นพร้อมกัน อันดับในช่วงทดสอบบอกได้ดีกว่าว่าการเลือกของเรามีค่าหรือเปล่า
- ใช้ walk-forward เมื่อตั้งใจจะ optimize ซ้ำ ถ้าในการใช้งานจริงเราจะเลือกพารามิเตอร์ใหม่เป็นระยะ backtest ก็ควรทำแบบเดียวกัน และนับต้นทุนจากการเปลี่ยนคู่ด้วย
- ลองกับข้อมูลที่ไม่มีสัญญาณ ถ้ากระบวนการของเราหาผลที่ดูดีได้แม้ในข้อมูลสุ่ม ผลดีบนข้อมูลจริงก็ต้องหักส่วนนั้นออกก่อน
ทุกข้อข้างบนยังอยู่บน SPY ตัวเดียวกับประวัติศาสตร์ 20 ปีชุดเดียว ผลที่ผ่านทุกข้อยังเป็นผลจำลองบนราคาที่ปรับย้อนหลัง ยังไม่รวม spread slippage ภาษี และข้อจำกัดของการส่งคำสั่งจริง
ลองรันเอง
ดาวน์โหลด Notebook ที่รันแล้ว · Python example · ราคา SPY จาก Webull (CSV) · ผลคำนวณ JSON · Markdown บทนี้
lesson_15.py ใช้แค่ Python standard library อ่านราคา SPY จากไฟล์ data/spy-webull-daily.csv ชุดเดียวกับบทที่ 4 ถ้าดาวน์โหลดแยกไฟล์ ให้วาง CSV ไว้ในโฟลเดอร์ data ข้างสคริปต์ ไม่เรียก API ใหม่ รันกี่ครั้งก็ได้ตัวเลขเดิม ใช้เวลาไม่ถึง 10 วินาที
python3 lesson_15.py --output-dir outputลองแก้แล้วรันใหม่ทีละอย่าง
- เปลี่ยน
IN_SAMPLEและOUT_OF_SAMPLEให้แบ่งที่ปี 2011 หรือ 2021 คู่ที่ชนะช่วงฝึกเปลี่ยนไปไหม และอันดับในช่วงทดสอบเป็นอย่างไร - ใน
build_results()เปลี่ยนbest(ins)เป็นbest(ins, 'cagr')เพื่อเลือกด้วย CAGR แทน Sharpe คู่ที่ได้ต่างจากเดิมแค่ไหน - เพิ่ม
FEEเป็น 0.002 แล้วดูว่าคู่ที่ EMA เร็วสั้น ๆ อย่าง 5/90 ซึ่งเทรด 46 ครั้งใน 20 ปี เสียเปรียบขึ้นเท่าไร - เปลี่ยน
WALK_TRAIN_YEARSจาก 5 เป็น 3 หรือ 8 คู่ที่ถูกเลือกกระโดดน้อยลงหรือมากขึ้น
- 1ข้อ 1
- 2ข้อ 2
- 3ข้อ 3
- 4ข้อ 4
- 5ข้อ 5
แหล่งข้อมูลและขอบเขต
- Yves Hilpisch, Python for Algorithmic Trading: From Idea to Cloud Deployment, O'Reilly, 2020. ใช้ไฟล์
python for algorithmic trading book (js).pdfที่แนบมา หน้า PDF 87–88 เรื่องoptimize_parametersแบบ brute force กับ SMA บน EUR/USD, หน้า 100–101 เรื่อง Data Snooping and Overfitting และหน้า 118 เรื่องการ fit ในช่วง in-sample แล้วประเมินใน out-of-sample เลขหน้าเป็นลำดับหน้า PDF เริ่มที่ 1 - White (2000) A Reality Check for Data Snooping, Bailey, Borwein, López de Prado และ Zhu (2015) The Probability of Backtest Overfitting และบทความเรื่อง overfitting ของ Man Institute อ้างผ่านหนังสือของ Hilpisch หน้า PDF 100–101 เท่านั้น เรายังไม่ได้อ่านต้นฉบับของงานเหล่านี้
- Webull Thailand · List Stock Historical Bars ที่มาของราคา SPY รายวัน ดึงเมื่อ 28 กันยายน 2026 ตามรายละเอียดและ checksum ในบทที่ 4 บทนี้ใช้ไฟล์เดิมโดยไม่ดึงใหม่
- โครงหัวข้อของคอร์ส Foundations of Alpha: The Theory Behind Algorithmic Trading (Hudson and Thames) ส่วน Research และ Risks in Models และคอร์ส Algorithmic Trading A-Z with Python, Machine Learning & AWS ส่วน Finding the optimal SMA Strategy, Overfitting และ Out-Sample Forward Testing ใช้เป็นแนวในการเรียงเนื้อหา ตรวจจากหน้าแนะนำคอร์สเมื่อ 29 กันยายน 2026 ไม่ได้ใช้เนื้อหาในวิดีโอ
การทดลองทั้งหมดในบทนี้ ทั้ง grid 484 คู่ การแบ่งช่วง ตลาดสุ่ม 60 โลก และ walk-forward เป็นการออกแบบใหม่สำหรับบทนี้ ตัวเลขทุกตัวคำนวณจาก lesson_15.py ภาพเรื่องเล่า Quantara สร้างด้วย Codex CLI โดยใช้ภาพเรื่องเล่าของบทที่ 3 เป็นต้นแบบสไตล์ เป็นภาพประกอบเรื่องสมมติ ไม่ได้แสดงข้อมูลใด ๆ