top of page
Robo Trade NotesContents
Hide contentsChapter 3
Backtesting / Research / Validation

Introduction of Backtest

ผมสามารถหา Strategy ที่มีกำไรได้เสมอ และ Backtest ที่ดูดีแทบไม่บออกอะไรอณาคตเลย แล้วเหตุใดเราถึงต้องทำ Back test ในบทนี้เราจะมาทำความเข้าใจการใช้งาน Backtest ข้อจำกัด และประโยชน์ของมัน

Backtest ตอบคำถามอะไร

Backtest คือการนำกฎซื้อขายและบริหารความเสี่ยงมาจำลองกับข้อมูลในอดีต เพื่อศึกษาพฤติกรรมของกลยุทธ์ เราต้องกำหนดด้วยว่าจะซื้อขายเมื่อไร ใช้ราคาใด และเสียต้นทุนเท่าไร แต่สิ่งที่ผู้คนเข้าใจผิดคือผลยุทธ์ที่ได้ผล Backtest ที่ดีจะเป็นกลยุทธ์ที่ดี Backtest คือการทดสอบกลยุทธ์กับข้อมูลอดีต ไม่ใช่หลักฐานว่าผลลัพธ์ในอนาคตจะเหมือนเดิม ปัญหาหลักคือข้อมูลอดีต

"ผมสามารถหากลยุทธ์ที่ดีในอดีตได้เสนอ แต่ในอนาคตไม่แน่"

นอกจากกำไรหรือขาดทุน เราอยากรู้ว่าต้องใช้เงินเท่าไร ถือสถานะมากเพียงใด ซื้อขายถี่แค่ไหน เจอช่วงขาดทุนประมาณไหนและนานเท่าไร และต้นทุนมีโอกาสกินความได้เปรียบจนหมดหรือไม่

หลักคิด: กระบวนการวิจัย

Backtesting is not a research tool. If a strategy does not perform well in a backtest, do not tweak it (overfit) until the backtest looks good. Instead, investigate how the research process misled you into backtesting a false strategy. Fix the research process, not the strat.

Backtesting มีความสำคัญมากในกระบวนการพัฒนาและประเมิน กลยุทธ์การลงทุนเพื่อให้เราเข้าใจถึงผลตอบแทนและความเสี่ยงสำหรับการเพิ่มประสิทธิภาพและสามารถปรับปรุงความแม่นยำของกลยุทธ์หรือแบบจำลองได้โดยการระบุจุดอ่อนหรืออคติที่อาจส่งผลให้ประสิทธิภาพไม่ดีในอดีต

อย่างไรก็ตาม Backtesting ไม่ใช่ Academic Research Tool เราทำการ Backtest เพื่อเข้าใจพฤติกรรมของกลยุทธ์เท่านั้น เราไม่ได้ใช้การ Backtes เพื่อทดสอบสมมุติฐานของกลยุทธ์ของเรา เรายังต้องพึงเครื่องอื่นๆ เช่นการทดสอบความเชื่อมั่น ทฤษฏีหรือแนวคิดที่ใช้ทดสอบกลยุทธ์ของเรา

เมื่อเราใช้ผลชุดทดสอบกลับไปเลือกกฎ ชุดนั้นก็เป็นส่วนหนึ่งของการพัฒนาแล้ว การทดสอบกฎที่แก้ใหม่กับข้อมูลเดิมจึงยังบอกไม่ได้ว่าจะได้ผลกับข้อมูลที่ไม่เคยเห็น

Backtest สามประเภท กับเครื่องมือสองแบบ

เราแบ่ง backtest ได้ทั้งตามข้อมูลที่นำมาทดสอบ และตามกลไกของการจำลอง

แกนที่หนึ่ง: เราทดสอบกับเส้นทางแบบใด

ประเภทตาม The Three Types of Backtestsวิธีคิดสิ่งที่ยังตอบไม่ได้
Historical / walk-forwardใช้ข้อมูลในอดีตจริงประวัติศาสตร์มีเส้นทางเดียว สิ่งที่เคยได้ผลอาจไม่เกิดซ้ำ
Resamplingนำข้อมูลในอดีตจริงเดิมมาจัดชุดใหม่ เช่น bootstrap หรือ cross-validation เพื่อดูผลหลายชุดต้องออกแบบให้เคารพความสัมพันธ์ตามเวลาและข้อมูลที่ทับซ้อน ไม่ใช่สุ่มสลับแถวได้เสมอ
Monte Carloจำลองเส้นทางจากกระบวนการกำเนิดข้อมูลที่สมมติขึ้นผลผูกกับความสมเหตุสมผลของแบบจำลอง จำนวนเส้นทางมากขึ้นไม่ได้พิสูจน์ว่าแบบจำลองตลาดถูกต้อง

Historical / walk-forward: เลื่อนช่วงฝึกและทดสอบไปตามเวลา

วิธีนี้ใช้ข้อมูลในอดีตจริง ภาพด้านล่างแสดงตัวอย่าง sliding window: แต่ละรอบใช้ข้อมูล 3 ช่วงก่อนหน้าเพื่อฝึก แล้วทดสอบกับ 1 ช่วงถัดไป จากนั้นเลื่อนหน้าต่างไปข้างหน้า ทุกแถวยังอยู่บนประวัติศาสตร์ชุดเดียว

Historical / walk-forward: เจ็ดรอบของหน้าต่างฝึกสามช่วง ตามด้วยช่วงทดสอบหนึ่งช่วง เลื่อนไปตามเวลา

สีม่วงคือช่วงฝึก ส่วนสีเขียวคือช่วงทดสอบ การกำหนดกฎและขั้นตอนปรับโมเดลควรทำไว้ก่อน การย้อนกลับไปแก้กฎหลังดูผลช่วงทดสอบทำให้ช่วงนั้นมีส่วนในการพัฒนาแล้ว

Resampling: จัดชุดใหม่จากข้อมูลเดิม

ภาพนี้แบ่งผลตอบแทนสมมติ 12 ช่วงเป็นบล็อก A–D บล็อกละ 3 ช่วง แล้วหยิบบล็อกมาเรียงเป็นสามชุด โดยหยิบซ้ำได้ เช่น ชุดใหม่ 1 มี D สองครั้ง ส่วนชุดใหม่ 2 มี C สองครั้ง ลำดับข้อมูลภายในแต่ละบล็อกยังเหมือนเดิม

Resampling: ข้อมูลเดิมแบ่งเป็นบล็อก A B C D จัดใหม่เป็น BDDA CABC และ ADCB พร้อมตัวอย่างช่วงฝึกและทดสอบในแต่ละชุด

แถบใต้แต่ละชุดแสดงตัวอย่างการแบ่งช่วงฝึกและทดสอบบนลำดับที่จัดใหม่ เส้นเวลาตรงนี้จึงเป็นลำดับของชุด resample ไม่ใช่ประวัติศาสตร์จริงอีกเส้นทาง รอยต่อระหว่างบล็อกเปลี่ยนไป และการแบ่งช่วงเพียงอย่างเดียวไม่ได้รับประกันว่าไม่มีข้อมูลรั่ว โดยเฉพาะเมื่อข้อมูลต้นทางเดียวกันถูกหยิบซ้ำมาอยู่ทั้งช่วงฝึกและทดสอบ

นี่เป็นตัวอย่าง block bootstrap ส่วน cross-validation ใช้แผนแบ่งข้อมูลเพื่อพัฒนาและประเมิน ไม่จำเป็นต้องหยิบบล็อกซ้ำอย่างในภาพ ทั้งสองวิธีต้องออกแบบให้เหมาะกับความสัมพันธ์ตามเวลาและข้อมูลที่ทับซ้อน

Monte Carlo: สร้างแบบจำลองจากสมมติ

Monte Carlo Backtesting หรือ Monte Carlo Simulation ในการทดสอบกลยุทธ์ คือกระบวนการทางสถิติที่นำผลลัพธ์จากการทดสอบย้อนหลัง (Backtest) มาสุ่มสลับลำดับหรือจำลองซ้ำเป็นพัน ๆ ครั้ง เพื่อประเมินความเสี่ยงและหาความเป็นไปได้ของผลตอบแทนในอนาคตภายใต้ความไม่แน่นอน

ดูเหมือนว่าเครื่องมือนี้ถูกออกแบบมาเพื่อ 'คาดการณ์' ความผันผวนของมูลค่าพอร์ต (equity) ที่อาจเกิดขึ้นเปรียบเทียบกันระหว่างกลยุทธ์ต่างๆ (เช่น กลยุทธ์นั้นล้มเหลวบ่อยแค่ไหน มีโอกาสเกิดผลกำไรต่อเนื่องกันมากน้อยเพียงใด และมีค่าเฉลี่ยของช่วงที่พอร์ตติดลบหรือ Drawdown เป็นอย่างไร) นี่คือความเข้าใจของผมเกี่ยวกับวิธีการใช้งานเครื่องมือนี้ กล่าวคือ มีการตั้งสมมติฐานเกี่ยวกับกลยุทธ์ไว้มากมาย (โดยอาศัยข้อมูลจากการทดสอบย้อนหลังหรือ backtesting) จากนั้นจึงนำกลยุทธ์ทั้งหมดมาเปรียบเทียบกันเพื่อเก็บข้อมูลของแต่ละกลยุทธ์

โดยพื้นฐานแล้ว วิธีการแบบ Monte Carlo นั้นถูกออกแบบมาเพื่อเปรียบเทียบกระบวนการสุ่ม (stochastic processes) รวมถึงตัวแปรสุ่มและฟังก์ชันการแจกแจงความน่าจะเป็นเพื่อทดสอบกลยุทธ์ทั้งหมดเพื่อหาค่าคาดหวังของผลกำไร (gain expectancy หรือ expectancy ratio) หรือที่เรียกกันว่า "สมการของเทรดเดอร์" (trader's equation)

จากนั้น เมื่อทราบแล้วว่ากลยุทธ์ใดให้ผลลัพธ์ที่ดี (จากการทดสอบย้อนหลัง) ก็จะใช้วิธี Monte Carlo เพื่อจำลองผลลัพธ์การเทรดที่อาจเกิดขึ้น โดยตั้งสมมติฐานว่ากลยุทธ์เหล่านั้นจะทำงานได้เหมือนกับที่เห็นในการทดสอบย้อนหลัง และสมมติฐานรวมถึงการคำนวณทั้งหมดของคุณนั้นถูกต้องแม่นยำ ตลอดจนเชื่อมั่นว่ากลยุทธ์ดังกล่าวจะยังคงใช้ได้ผลดีในสถานการณ์ตลาดจริงในอนาคต

ตัวอย่างนี้เริ่มดัชนีราคาที่ 100 แล้วสมมติว่าแต่ละช่วงขึ้น 2% หรือลง 2% ด้วยโอกาสเท่ากัน และแต่ละช่วงเป็นอิสระต่อกัน เมื่อสุ่มซ้ำได้ 100 เส้นทาง เส้นละ 12 ช่วง เราจึงเห็นผลหลายแบบจากกฎเดียวกัน บางเส้นซ้อนกันเพราะแต่ละช่วงมีผลตอบแทนให้เลือกเพียงสองค่า

Monte Carlo: เส้นทางราคาสมมติ 100 เส้น เริ่มที่ 100 และสุ่มขึ้นหรือลง 2 เปอร์เซ็นต์ต่อช่วง

หากเพิ่มจำนวนเส้นทาง เราจะเห็นผลจากกฎนี้มากขึ้น ส่วนข้อสมมติว่าราคาขึ้นลง 2% และแต่ละช่วงเป็นอิสระ ยังต้องตรวจแยกว่าตรงกับตลาดที่ต้องการศึกษาหรือไม่ [2, หน้า PDF 3–5]

ภาพ Historical (PNG) · ภาพ Resampling (PNG) · ภาพ Monte Carlo (PNG)

แกนที่สอง: กลไกการเขียน code

Vectorized backtest คำนวณสัญญาณ สถานะ และผลตอบแทนเป็นชุดด้วยตารางหรือ array เหมาะกับกฎที่เขียนความสัมพันธ์ตามเวลาได้ชัดเจน ใส่ต้นทุนตามมูลค่าซื้อขายได้ เช่น ตัวอย่างในหนังสือ [1, หน้า PDF 75–76, 94–95]

Event-based หรือ event-driven backtest ประมวลผลเหตุการณ์ตามลำดับ เช่น ข้อมูลมาถึง เกิดสัญญาณ ส่งคำสั่ง จับคู่ และอัปเดตเงินสด/หุ้น เหมาะเมื่อการทำงานขึ้นกับสถานะสะสมหรือรายละเอียดคำสั่ง แต่ความสมจริงยังขึ้นกับแบบจำลองการจับคู่ สภาพคล่อง และข้อจำกัดที่ใส่ไว้ [1, หน้า PDF 148–152]

สองมิตินี้ใช้ร่วมกันได้ เช่น ทดสอบข้อมูล historical ด้วยเครื่องจำลอง event-based การเปลี่ยนสถาปัตยกรรมอย่างเดียวไม่ทำให้ bias หายไป

ออกแบบการทดสอบ

เริ่มจากคำอธิบายที่หักล้างได้ เช่น “กฎนี้คาดว่าจะได้ประโยชน์จากแนวโน้มที่ต่อเนื่อง หลังรวมต้นทุนที่กำหนด” แล้วเขียนล่วงหน้าว่าข้อมูล สัญญาณ การถือสถานะ และหลักฐานแบบใดจะทำให้ไม่เชื่อสมมติฐานนี้

Split window แบ่งข้อมูลตามเวลา: ชุด A ใช้พัฒนา ส่วนชุด B ที่ตามมาทีหลังใช้ประเมินกฎที่กำหนดไว้แล้ว Sliding window เลื่อนช่วงฝึกและทดสอบไปข้างหน้า แต่ละรอบต้องเรียนรู้จากข้อมูลก่อนช่วงที่ประเมินเท่านั้น การปรับโมเดลตามตารางที่กำหนดไว้ล่วงหน้าเป็นคนละเรื่องกับการย้อนแก้กฎหลังเห็นคำตอบ

ในงานที่มีการเลือกพารามิเตอร์ อาจแยก train สำหรับเรียนรู้, validation สำหรับเลือกแบบจำลอง และ final test สำหรับตรวจท้ายสุด รายการที่ต้อง fit เช่น scaler หรือการเลือกตัวแปร ต้องอยู่ในข้อมูลฝึกของรอบนั้นด้วย หากดู final test แล้วปรับกฎ ชุดนั้นถูกใช้พัฒนาไปแล้ว ก่อนรัน ให้บันทึกอย่างน้อย:

  1. เหตุผลของกลยุทธ์ กฎเข้า/ออก และวิธีวัดว่าผ่านหรือไม่ผ่าน
  2. สินทรัพย์ ช่วงข้อมูล ความถี่ เขตเวลา และวิธีจัดการข้อมูลหายหรือแก้ย้อนหลัง
  3. เวลาที่รู้ข้อมูล เวลาส่งคำสั่ง ราคา fill และข้อจำกัดการถือสถานะ
  4. ต้นทุน เกณฑ์เปรียบเทียบ จำนวนการทดลอง และวิธีเก็บผลที่ไม่ผ่านด้วย

การปรับพารามิเตอร์ระหว่างพัฒนา ส่วน protocol กำหนดให้แยกผลจากข้อมูลพัฒนาออกจากผลบนข้อมูลที่ยังไม่เคยเห็น

จาก Signal ไปสู่ Position

Signal คือสัญญาณซื้อขายจากกฎ เช่น อยากถือหุ้นหรืออยากถือเงินสด ส่วน position คือสถานะที่มีอยู่จริงและรับผลตอบแทนในช่วงนั้น ระหว่างสองสิ่งนี้ยังมีการส่งคำสั่งและการจับคู่ หรือ fill

แยกการตัดสินใจเป็นสองส่วนได้:

  • Side บอกทิศทาง ในบทนี้ใช้ st∈{0,1}s_t \in \{0,1\} คือเงินสดหรือ long
  • Size บอกขนาดของเงิน at∈[0,1]a_t \in [0,1] เป็นสัดส่วนพอร์ต

น้ำหนักเป้าหมายจึงเป็น wt=statw_t=s_t a_t สัญญาณเหมือนกันไม่ได้แปลว่าความเสี่ยงเหมือนกัน หากกลยุทธ์หนึ่งลงเงิน 100% แต่อีกกลยุทธ์ลงเพียง 40%

ตัวอย่างสมมติ: ก่อนเริ่มช่วงราคา 100 → 110 เราถือเงินสด ผลจากหุ้นของพอร์ตจึงเป็นศูนย์ ต่อให้เมื่อสิ้นช่วง กฎเพิ่งให้สัญญาณซื้อ การนำสัญญาณใหม่นั้นไปคูณผลตอบแทน +10% ที่ผ่านไปแล้วก็คือการให้ระบบย้อนเวลา

ในทางกลับกัน หากถือ short น้ำหนัก −1 ก่อนช่วงเดียวกัน ผลตอบแทนจากหุ้นจะเป็น −10% ก่อนต้นทุน ไม่ใช่กำไรเพราะสัญญาณตอนท้ายเพิ่งเปลี่ยนเป็น long ตัวอย่าง short นี้ใช้สอนบัญชีผลตอบแทนเท่านั้น ห้องทดลองด้านล่างไม่เปิด short

Look-ahead bias: รู้คำตอบเร็วเกินไป

Backtest ที่ใช้ราคาปิดไปซื้อที่ราคาเปิดของวันเดียวกัน ก็เหมือนใส่จดหมายตอนเย็นลงในช่องตัดสินใจตอนเช้า ในสมุดจึงต้องลงทั้งเวลาที่ข้อมูลมาถึงและเวลาที่ส่งคำสั่ง

Look-ahead bias เกิดเมื่อการตัดสินใจในอดีตใช้ข้อมูลที่ยังไม่พร้อม ณ เวลานั้น ไม่ว่าจะมาจากราคาปิดของวันเดียวกัน งบที่ยังไม่ประกาศ หรือสถิติที่คำนวณจากข้อมูลทั้งชุด [2, หน้า PDF 7; 4, หน้า PDF 16]

ในบทนี้กำหนดลำดับเวลาให้ชัดเจน:

เวลาสิ่งที่ทำได้ในตัวอย่าง
หลังตลาดปิด session t−1t-1ใช้ราคาปิดถึง t−1t-1 คำนวณ SMA สัญญาณ และความผันผวน
ราคาเปิด session ttสมมติว่าคำสั่งที่เตรียมไว้จับคู่ได้ที่ราคาเปิด แล้วปรับน้ำหนักพอร์ต
ราคาเปิด session t+1t+1วัดผลจากช่วงเปิดถึงเปิด และเตรียมรอบถัดไป

ให้ OtO_t คือราคาเปิดของ session tt ผลตอบแทนของสินทรัพย์ในช่วงถือครองคือ

Rt→t+1=Ot+1Ot−1.R_{t\to t+1}=\frac{O_{t+1}}{O_t}-1.

น้ำหนักที่ใช้รับผลตอบแทนนี้ต้องอาศัยข้อมูลที่พร้อมก่อนเปิด tt ในกรณีปกติของเรา จึงใช้สัญญาณจากราคาปิด t−1t-1 ส่วนกรณีผิดในห้องทดลองจะใช้ราคาปิด tt เพื่อซื้อที่ราคาเปิด tt ซึ่งยังรู้ไม่ได้

ใน pandas มักเห็น signal.shift(1) แต่ต้องอ่านความหมายของ index และผลตอบแทนก่อน ตัวอย่างโครงสร้างสำหรับ convention ข้างต้นคือ:

PYTHON
pythonคัดลอก
# close and open are aligned by session index.side_at_close = (close.rolling(20).mean() > close.rolling(50).mean()).astype(float)weight_at_open = side_at_close.shift(1)open_to_next_open = open.shift(-1) / open - 1# Gross return only: warm-up, sizing, costs and liquidation are handled separately.gross = weight_at_open * open_to_next_open

แม้เลื่อนสัญญาณหนึ่งแถวแล้ว หากใช้ volatility ของอนาคตในการกำหนด size ก็ยังมีข้อมูลอนาคตรั่วเข้ามา และแม้ใช้ข้อมูลทันเวลา สมมติฐานว่า fill ได้ที่ราคาเปิดยังต้องตรวจในระบบซื้อขายจริง ทั้งเรื่องเวลาตัดรับคำสั่ง สภาพคล่อง และ slippage

ลองเปิดข้อมูลตามเวลาที่รู้ได้

แบบจำลองย่อนี้ใช้กฎ ราคาปิดล่าสุดมากกว่า 100 ให้ Long มิฉะนั้นถือเงินสด เพื่อให้เห็นเรื่องเวลาอย่างเดียว จึงแยกจากกฎ SMA 20/50 ในห้องทดลองใหญ่ ลองเดินจากตอนเปิด session 1 ไปจนถึงเปิด session 2 แล้วดูว่าข้อมูลใดเพิ่งปรากฏ และสถานะใดรับผลตอบแทนไปแล้ว

LOOK-AHEAD BIAS

รู้ราคาปิดแล้ว ย้อนกลับไปซื้อที่ราคาเปิดได้ไหม?

กติกาสมมติ: ราคาปิดล่าสุด > 100 ให้ Long มิฉะนั้น Cash ส่งคำสั่งได้ที่ราคาเปิดถัดไป ตัวอย่างนี้แยกจากกติกา SMA 20/50 ในแล็บหลัก

1 · เปิด session 12 · ปิด session 13 · เปิด session 2

ตอนเปิด session 1 รู้ราคาปิด session 0 เท่ากับ 99 กติกาจึงให้ถือ Cash ราคาปิดของวันนี้และราคาเปิดพรุ่งนี้ยังไม่ทราบ

ราคาสมมติ · หน่วยเงินต่อหุ้น
ราคาที่รู้แล้ว เทียบกับราคาที่ยังไม่เกิดขึ้นเหตุการณ์เรียงจาก close 0, open 1, close 1 ถึง open 2 ขณะนี้อยู่ที่ open 1 เส้นทึบเป็นข้อมูลที่รู้แล้ว เส้นประถ้าปรากฏเป็นเฉลยข้อมูลอนาคตที่ใช้ตัดสินใจไม่ได้ ค่าที่ไม่ทราบจะแสดงเครื่องหมายคำถาม9610010410811299close 0รู้แล้ว100open 1รู้แล้ว?close 1อนาคต?open 2อนาคต

แกนนอนเรียงเหตุการณ์ ระยะห่างไม่ได้แทนเวลาจริง · พื้นสีเทาคืออนาคต ณ จุดที่เลือก

ลองเปิดเฉลยข้อมูลอนาคตข้อมูลที่ยังไม่เกิดขึ้นถูกซ่อนไว้
ตามเวลาจริง · ใช้ close 0CASH ที่ open 1

ผลช่วง open 1–open 2

0% · ยังไม่สิ้นช่วง
INVALID · เอา close 1 มาใช้ที่ open 1close 1 ยังไม่ทราบ

ผลที่ backtest ผิดวิธีจะอ้าง

รอราคา open 2

สัญญาณใหม่แก้สถานะในอดีตไม่ได้ การเปิดเฉลยเปลี่ยนสิ่งที่เราเห็นบนจอ แต่ไม่เปลี่ยนข้อมูลที่ผู้ซื้อขายรู้ในตอนนั้น

ตัวอย่างสมมติจาก close 0 ถึง open 2 · หุ้นเศษส่วนได้ · Long = ลงหุ้นทั้งหมด, Cash = เงินสดทั้งหมด · ไม่คิดต้นทุนและดอกเบี้ย · ไม่มีข้อมูลตลาดจริง

จากผลตอบแทนสินทรัพย์สู่มูลค่าพอร์ต

สำหรับพอร์ต long กับเงินสดที่ให้ดอกเบี้ยศูนย์ หากน้ำหนักหุ้นหลังปรับพอร์ตคือ wtw_t และยังไม่คิดต้นทุน ผลตอบแทนพอร์ตในหนึ่งช่วงคือ wtRt→t+1w_tR_{t\to t+1} สูตรนี้ใช้ simple return หรือผลตอบแทนเทียบกับราคาเริ่มต้นของช่วง

เมื่อต้องเสียค่าใช้จ่าย ให้คิดสองขั้นตอน:

Vt+=Vt−−Ct,Vt+1−=Vt+(1+wtRt→t+1).V_t^{+}=V_t^{-}-C_t, \qquad V_{t+1}^{-}=V_t^{+}\left(1+w_tR_{t\to t+1}\right).

Vt−V_t^{-} คือมูลค่าก่อนซื้อขาย, CtC_t คือต้นทุน, Vt+V_t^{+} คือมูลค่าหลังจ่ายต้นทุน และ wtw_t คือสัดส่วนหุ้นของมูลค่าหลังจ่ายต้นทุนนั้น

Turnover คือมูลค่าที่ซื้อขายเทียบกับมูลค่าพอร์ต ห้องทดลองคิดต้นทุนตาม notional ที่ซื้อขายจริงในแบบจำลอง รวมการซื้อครั้งแรก การปรับน้ำหนัก และการขายออกตอนจบ โดยคำนึงว่าน้ำหนักหุ้นเคลื่อนตามราคา แม้ target weight จะเท่าเดิม

หน่วยต้นทุนใช้ basis point (bp): 1 bp = 0.01% ดังนั้น 5 bps = 0.05% ต่อมูลค่าซื้อขาย ไม่ใช่ 5% และไม่ใช่ค่าธรรมเนียมคงที่ต่อวัน

หากซื้อขายมูลค่า 10,000 หน่วยด้วยอัตรา 5 bps ต้นทุนเท่ากับ 5 หน่วย การกลับจาก short เต็มพอร์ตเป็น long เต็มพอร์ตมี notional โดยประมาณสองเท่าของการเปลี่ยนจากเงินสดเป็น long จึงไม่ควรนับเป็นต้นทุนเพียง “หนึ่งสัญญาณ”

อัตราในห้องทดลองเป็นสมมติฐานรวมแบบย่อ ไม่ใช่อัตราค่าธรรมเนียมของโบรกเกอร์ใด แบบจำลองนี้ยังไม่จำลอง market impact, partial fill, fixed commission หรือข้อจำกัดสภาพคล่อง จึงใช้ตรวจกลไกเบื้องต้น ไม่ใช่ execution simulator เต็มรูปแบบ [1, หน้า PDF 94–95, 151–152; 2, หน้า PDF 7–8]

Volatility targeting: คุมขนาดความเสี่ยง

Volatility targeting คือการปรับขนาดสถานะตามความผันผวนที่ประเมินได้ เช่น เมื่อสินทรัพย์แกว่งแรงขึ้น ใช้เงินกับสถานะเดิมน้อยลง แนวคิดนี้แยกจากสัญญาณว่าจะซื้อหรือไม่ซื้อ

หาก σ∗\sigma^* คือเป้าความผันผวนต่อปี และ σ^t−1\widehat\sigma_{t-1} คือความผันผวนที่ประมาณจากข้อมูลถึงวันก่อนหน้า เรากำหนดขนาดอย่างง่ายเป็น

at=min⁡(1,σ∗σ^t−1),wt=st−1at.a_t=\min\left(1,\frac{\sigma^*}{\widehat\sigma_{t-1}}\right), \qquad w_t=s_{t-1}a_t.

เพดาน 1 หมายถึงไม่ใช้ leverage ถ้าเป้าคือ 10% ต่อปี แต่สินทรัพย์มี estimated volatility 20% จะถือประมาณ 50% ของพอร์ตเมื่อ signal เป็น long หาก estimated volatility เป็น 5% สูตรดิบให้ 200% แต่เพดานในบทนี้จำกัดเหลือ 100%

ห้องทดลองใช้ sample standard deviation ของผลตอบแทนปิดถึงปิดย้อนหลัง 20 ช่วง แล้วคูณ 252\sqrt{252} เพื่อแปลงเป็นรายปี การคำนวณทุกครั้งใช้หน้าต่างย้อนหลังของจุดเวลานั้น เริ่มประเมินหลังมีข้อมูลครบ และหาก volatility เป็นศูนย์จะไม่เปิดสถานะในโหมด targeting

เป้าความผันผวนไม่ใช่ drawdown limit และไม่รับประกันว่า volatility ที่เกิดจริงจะตรงเป้า โดยเฉพาะเมื่อพอร์ตสลับถือเงินสด มีเพดานน้ำหนัก หรือความผันผวนเปลี่ยนเร็ว การ targeting อาจลดทั้งกำไรและขาดทุน และเพิ่ม turnover จากการปรับ size แม้ side ไม่เปลี่ยน [5; 3, หน้า 10]

ลองคงสัญญาณ Long แล้วเพิ่มค่าความผันผวนด้านล่าง น้ำหนักหุ้นจะลดลงตามสูตร ส่วนที่เหลืออยู่ในเงินสด จากนั้นเปลี่ยนสัญญาณเป็น Cash แล้วดูว่าน้ำหนักหุ้นเหลือเท่าไร

VOLATILITY TARGETING

ลดน้ำหนักอย่างไรให้ความเสี่ยงเข้าใกล้เป้า?

เมื่อความผันผวนของสินทรัพย์สูงขึ้น ใช้เงินลงทุนน้อยลงได้โดยไม่ต้องเปลี่ยนกติกาสัญญาณ ทดลองแบ่งพอร์ตสมมติ 100 หน่วยระหว่างหุ้นกับเงินสด

เป้า Vol ของพอร์ตต่อปี 10%5–20% ต่อปีVol สินทรัพย์ที่ประเมินได้ 20%5–40% ต่อปี · สมมติว่าประเมินก่อนตัดสินใจ
สัญญาณขณะนี้
LongCash
หุ้น 50.0%เงินสด 50.0%

น้ำหนักหุ้น = min(1, 10% ÷ 20%) = 50.0%

Vol พอร์ตที่ประมาณจากน้ำหนักนี้10.0%น้ำหนักหุ้น × Vol สินทรัพย์

เงินส่วนที่ไม่ลงหุ้นอยู่ในเงินสด เป้า Vol ใช้กำหนดขนาดสถานะ ไม่ได้เปลี่ยนสัญญาณ Long ให้ถูกต้องขึ้น

นี่คือการประมาณภายใต้สมมติฐานอย่างง่าย ความผันผวนที่เกิดจริงอาจต่างจากค่าที่ประเมิน และ Vol targeting ไม่ได้รับประกันว่าจะลด drawdown หรือไม่ขาดทุน

สมมติหุ้นหนึ่งตัว เงินสดให้ผลตอบแทน 0% และไม่มีความผันผวน · ไม่มี leverage · ใช้ Vol ต่อปีในหน่วยเดียวกัน · ไม่รวมต้นทุนและความคลาดเคลื่อนของการประมาณ

ในตัวอย่างนี้ หากปรับเป้าความผันผวนเป็น 20% แต่สินทรัพย์แกว่งเพียง 5% เพดานไม่ใช้ leverage จะทำให้ลงเงินได้สูงสุด 100% และความเสี่ยงตามสัดส่วนยังต่ำกว่าเป้า

เวลาและขนาดสถานะเปลี่ยน Backtest อย่างไร

ห้องทดลองใช้ราคาสมมติ 320 sessions ซึ่งสร้างด้วย seed 20260925 และใช้ชุดเดิมทุกครั้ง ราคาเป็นหน่วยสมมติ ไม่ได้อ้างถึงสินทรัพย์หรือวันที่ตลาดจริง

กฎคือ long เมื่อ SMA 20 ของราคาปิดสูงกว่า SMA 50 มิฉะนั้นถือเงินสด ค่าทั้งสองถูกกำหนดเพื่อสาธิตกลไก ไม่ได้เลือกจากผลตอบแทนที่ดีที่สุด ทุกกรณีเริ่มที่ราคาเปิด session 60 และจบที่ราคาเปิด session 319 รวม 259 ช่วงผลตอบแทน ใช้ทุนเริ่มต้น 100 หน่วย

กรณีข้อมูลที่ใช้ตัดสินใจเปิด ttขนาดเมื่อ long
Causal · fixed sizeราคาปิดถึง t−1t-1100%
Causal · vol targetราคาปิดถึง t−1t-1ปรับตาม volatility ถึง t−1t-1
Look-ahead · fixed sizeแอบใช้ราคาปิด tt100%
Look-ahead · vol targetแอบใช้ราคาปิดและ volatility ถึง ttปรับตามข้อมูลที่ยังไม่รู้

กรณี Look-ahead ทั้งสอง ซื้อขายตามเวลาจริงไม่ได้ ใส่มาเพื่อให้เห็นผลของความผิดพลาด ไม่ใช่ตัวเลือกกลยุทธ์ ส่วน buy-and-hold ในตารางใช้ช่วงเปิดถึงเปิดเดียวกัน รวมต้นทุนเข้าและออกเช่นเดียวกัน

SIGNAL TIMING / POSITION SIZE / COSTS

เวลาใช้สัญญาณและขนาดสถานะ เปลี่ยนผล Backtest อย่างไร?

ข้อมูลสังเคราะห์

เปรียบเทียบเวลาใช้ข้อมูลและการกำหนดน้ำหนักบนราคาเส้นเดียวกัน ทั้งสี่วิธีใช้ SMA 20/50 ชุดเดิม ลองเปลี่ยนต้นทุนและเป้าความผันผวน แล้วอ่านทั้งผลตอบแทนและความเสี่ยง

ต้นทุนต่อข้าง 5 bps0–20 bps · 1 bp = 0.01% ของมูลค่าซื้อขายเป้าความผันผวนต่อปี 10%5–20% · ใช้กับวิธี Vol targeting เท่านั้น

กติกาคงที่: SMA 20/50 · Vol ย้อนหลัง 20 ผลตอบแทน · ถือหุ้น 0–100% · ไม่ใช้ leverage

คืนค่าเริ่มต้น

เส้นทึบ: รู้ข้อมูลตามเวลา
เส้นประ: ใช้ข้อมูลอนาคต ทำจริงไม่ได้

มูลค่าพอร์ตDrawdown
  • 1. รู้ข้อมูลตามเวลา · น้ำหนักคงที่
  • 2. รู้ข้อมูลตามเวลา · Vol targeting
  • 3. แอบใช้ข้อมูลอนาคต · น้ำหนักคงที่
  • 4. แอบใช้ข้อมูลอนาคต · Vol targeting

ดัชนีมูลค่าพอร์ต เริ่มที่ 100

ดัชนีมูลค่าพอร์ต เริ่มที่ 100 · เปรียบเทียบ 4 วิธีบนข้อมูลสังเคราะห์แกนนอนเป็นลำดับ session 60 ถึง 319 เส้นทึบใช้ข้อมูลที่รู้ก่อนซื้อขาย เส้นประแอบใช้ข้อมูลอนาคตและทำจริงไม่ได้ ใช้ตัวเลื่อนใต้กราฟเพื่ออ่านค่าของทั้งสี่เส้น9010011012013060112164215267319

ลำดับ session สมมติ · ไม่มีวันที่ตลาดจริง

อ่านค่าที่ session 319
1. ตามเวลา · คงที่
113.17ดัชนีมูลค่าพอร์ต
2. ตามเวลา · Vol target
108.76ดัชนีมูลค่าพอร์ต
3. ข้อมูลอนาคต · คงที่
112.61ดัชนีมูลค่าพอร์ต
4. ข้อมูลอนาคต · Vol target
107.77ดัชนีมูลค่าพอร์ต
ผลหลังต้นทุน · 259 ช่วงผลตอบแทนเดียวกัน · session 60–319
วิธีทดสอบReturnCAGRVol / ปีSharpeMax DDTurnover
1. รู้ข้อมูลตามเวลา · น้ำหนักคงที่13.17%12.79%14.49%0.90-8.79%6.00×
2. รู้ข้อมูลตามเวลา · Vol targeting8.76%8.52%9.60%0.90-6.06%9.57×
3. แอบใช้ข้อมูลอนาคต · น้ำหนักคงที่ตัวอย่างข้อผิดพลาด · ทำจริงไม่ได้12.61%12.25%14.53%0.87-8.79%6.00×
4. แอบใช้ข้อมูลอนาคต · Vol targetingตัวอย่างข้อผิดพลาด · ทำจริงไม่ได้7.77%7.55%9.03%0.85-5.29%9.59×
ซื้อแล้วถือ · Buy and holdแถวอ้างอิง · ไม่แสดงในกราฟ15.56%15.11%16.58%0.93-10.73%2.00×

Return คือผลตอบแทนรวมในช่วงทดสอบ · CAGR, Vol และ Sharpe ใช้ 252 ช่วงต่อปี และอัตราปลอดความเสี่ยง 0% · Max DD วัดจากจุดมูลค่าพอร์ตที่ราคาเปิด ไม่รวมความเคลื่อนไหวระหว่างวัน และไม่ปรับเป็นรายปี · Turnover คือผลรวมสัดส่วนมูลค่าซื้อขายต่อพอร์ต ณ แต่ละการซื้อขาย รวมการเข้าครั้งแรกและปิดสถานะท้ายช่วง · ทุกวิธีใช้ต้นทุนต่อข้างเดียวกัน

ผลสูงหรือต่ำ ก็ใช้ข้อมูลอนาคตไม่ได้

วิธีรู้ข้อมูลตามเวลาใช้ราคาปิด t−1 ก่อนซื้อขายที่ราคาเปิด t ส่วนวิธีเส้นประใช้ราคาปิด t ย้อนกลับไปซื้อขายที่ราคาเปิด t จึงรู้สิ่งที่ยังไม่เกิดขึ้น ทั้งสัญญาณและค่า Vol ในวิธีเส้นประมี look-ahead bias ผลจึงใช้ประเมินการซื้อขายจริงไม่ได้ ไม่ว่าจะสูงหรือต่ำกว่า

Vol targeting ปรับขนาดการถือครอง และเป้าหมายอาจไม่เท่าความผันผวนที่เกิดจริง การปรับตัวเลื่อนนี้ใช้สำรวจสมมติฐาน ไม่ใช่ค้นหาค่าที่ทำให้ผลย้อนหลังสวยที่สุด

ชุดข้อมูลสังเคราะห์ 320 sessions · seed 20260925 · ประเมิน open-to-open ช่วง 60→61 ถึง 318→319 · เริ่มดัชนี 100 ก่อนต้นทุนเข้า และรวมต้นทุนปิดสถานะท้ายช่วง · เงินสดให้ผลตอบแทน 0% · ไม่มีข้อมูลตลาดหรือคำสั่งซื้อขายจริง

เริ่มจากเปรียบเทียบ fixed size กับ vol target ภายในกลุ่ม Causal ก่อน จากนั้นเทียบ Causal กับ Look-ahead โดยคงรูปแบบ size เดียวกัน วิธีนี้ช่วยไม่ให้สรุปผลจากสองสิ่งที่เปลี่ยนพร้อมกัน

ลองเพิ่มต้นทุนแล้วดูทั้งผลตอบแทนและ turnover การ targeting ไม่จำเป็นต้องได้ Sharpe สูงขึ้นทุกครั้ง และ look-ahead ก็ไม่จำเป็นต้องทำให้ทุก metric ดีขึ้นในทุกชุดข้อมูล ทั้งผลที่สูงขึ้นและต่ำลงยังใช้ประเมินการซื้อขายจริงไม่ได้ หากคำสั่งอาศัยข้อมูลที่ยังไม่เกิดขึ้น

การทดลองนี้เป็นตัวอย่างเชิงกลไก ไม่ใช่ out-of-sample validation ของ SMA และการเปลี่ยน cost/target ในหน้านี้ไม่ใช่หลักฐานสำหรับเลือกกลยุทธ์ลงทุน

อ่าน Tear sheet: ผลตอบแทนควบคู่ความเสี่ยง

Tear sheet คือรายงานย่อที่รวมผลตอบแทน ความเสี่ยง และพฤติกรรมของกลยุทธ์ไว้ด้วยกัน ก่อนอ่านตัวเลข ให้ดูช่วงเวลา ความถี่ จำนวนข้อมูล benchmark และนิยามต้นทุนก่อนเสมอ [5]

ตัววัดคำถามที่ตอบข้อควรอ่านประกอบ
Total returnเงินเริ่มต้นเปลี่ยนไปกี่เปอร์เซ็นต์ตลอดช่วงต้องดูระยะเวลาลงทุนและช่วงขาดทุนประกอบ
CAGRหากเติบโตด้วยอัตราทบต้นคงที่ต่อปี จะเท่ากับเท่าไรเป็นการย่อเส้นทาง ไม่ใช่ผลตอบแทนที่ได้รับเท่ากันทุกปี
Annualized volatilityผลตอบแทนแกว่งมากเพียงใดเมื่อแสดงเป็นรายปีขึ้นกับความถี่และสมมติฐานการ annualize
Sharpe ratioได้ผลตอบแทนส่วนเกินต่อความผันผวนเท่าไรต้องระบุ risk-free rate, ช่วงข้อมูล และการ annualize
Maximum drawdownจากจุดสูงสุดเดิม พอร์ตเคยตกลงลึกที่สุดเท่าไรเป็นตัววัดเส้นทางในช่วงตัวอย่าง ไม่ annualize
Turnoverต้องซื้อขายมากเพียงใดบทนี้เป็นผลรวม notional / equity ก่อนซื้อขายแต่ละครั้ง ไม่ใช่จำนวน trades

หากมี NN ช่วงผลตอบแทน และใช้สมมติฐาน 252 ช่วงต่อปี:

CAGR=(VNV0)252/N−1,σann=s(rnet)252.\mathrm{CAGR}=\left(\frac{V_N}{V_0}\right)^{252/N}-1, \qquad \sigma_{\mathrm{ann}}=s(r^{\mathrm{net}})\sqrt{252}.

ห้องทดลองกำหนด risk-free rate เป็นศูนย์และใช้ sample standard deviation ดังนั้น

Sharpe^=252rnet‾s(rnet).\widehat{\mathrm{Sharpe}}=\sqrt{252}\frac{\overline{r^{\mathrm{net}}}}{s(r^{\mathrm{net}})}.

Sharpe ในสูตรนี้ใช้ค่าเฉลี่ยผลตอบแทนรายช่วง ไม่ใช่นำ CAGR มาหาร volatility ถ้าความผันผวนเป็นศูนย์จะไม่รายงาน ratio การคูณรากของเวลาเป็น convention แบบย่อ ไม่ใช่ข้อยืนยันว่าผลตอบแทนไม่มี autocorrelation [1, หน้า PDF 85, 278]

นิยาม drawdown ที่ใช้ในกราฟคือ

Dt=Vtmax⁡0≤u≤tVu−1,MDD=min⁡tDt.D_t=\frac{V_t}{\max_{0\leq u\leq t}V_u}-1, \qquad \mathrm{MDD}=\min_t D_t.

ห้องทดลองวัดจากจุดมูลค่าที่ราคาเปิดแต่ละ session จึงไม่ครอบคลุมการขาดทุนระหว่างวัน เรารายงานเป็นค่าติดลบหรือศูนย์ เช่น เส้นพอร์ตสมมติ 100 → 110 → 88 → 100 → 120 จบด้วย total return +20% แต่เคยมี drawdown −20% จาก 110 ลง 88 และต้องรอจนกลับถึงยอดเดิมจึงฟื้นตัวเต็มที่ [1, หน้า PDF 279]

คำนวณผลตอบแทนที่ต้องได้เพื่อกลับทุน

จากยอด 100 ลงเหลือ 80 คือขาดทุน 20% แต่การบวกกลับ 20% ของ 80 ได้เพียง 16 จึงกลับมาแค่ 96 หากต้องการกลับถึงยอดเดิม ต้องเพิ่ม 20 จากฐาน 80 หรือ 25%

สำหรับสัดส่วนขาดทุน dd ที่อยู่ระหว่าง 0 กับ 1 อัตราฟื้นตัวที่ต้องการคือ

Recovery=11−d−1=d1−d.\mathrm{Recovery}=\frac{1}{1-d}-1=\frac{d}{1-d}.
DRAWDOWN & RECOVERY

ขาดทุน 20% ต้องฟื้นเท่าไรถึงทุนเดิม?

เปอร์เซ็นต์ขาดทุนคิดจากยอดเดิม แต่เปอร์เซ็นต์ฟื้นตัวคิดจากเงินที่เหลือ ฐานที่ต่างกันทำให้ตัวเลขขาลงและขากลับไม่เท่ากัน

ลดลงจากยอดสูงสุด 20%5–60% · ยอดเริ่มต้น 100
ดัชนีมูลค่าพอร์ต · ยอดเดิม = 100
ฟื้นด้วยเปอร์เซ็นต์เท่าที่ขาดทุน ยังกลับไม่ถึงยอดเดิมพอร์ตเริ่มที่ 100 ลดลง 20% เหลือ 80 แล้วเพิ่ม 20% จากฐานที่ต่ำลง ได้ 96 เส้นอ้างอิงที่ 100 คือเป้ากลับทุนเดิม0255075100100ยอดเดิม80หลังขาดทุน96ฟื้น %เท่าที่เสีย

เส้นอ้างอิงสีเขียว = ทุนเดิม 100 · ตัวเลขบนเส้นม่วงคือมูลค่าจริงของตัวอย่างแต่ละช่วง

ถ้าฟื้นเพียง 20%96ยังต่ำกว่ายอดเดิม 100
ต้องฟื้นจาก 80 ให้ถึง 100+25.00%คิดจากมูลค่าหลังขาดทุน

ผลตอบแทนที่ต้องได้ = 20% ÷ (1 − 20%) = 25.00%

ที่ขาดทุน 20% พอร์ตเหลือ 80 การเพิ่ม 20% ของฐานนี้ได้ 16 หน่วย จึงจบที่ 96 ไม่ใช่ 100

ตัวอย่างเลขคณิตสมมติ 3 จุด ไม่มีต้นทุนหรือเงินไหลเข้าออก · ไม่ได้ทำนายว่าจะฟื้นตัวได้จริง · Drawdown วัดการลดลงจากยอดสูงสุดและไม่ปรับเป็นรายปี

กราฟนี้เป็นตัวอย่างเลขคณิตของมูลค่าพอร์ต ไม่ใช่การพยากรณ์ว่าพอร์ตจะฟื้นจริงหรือใช้เวลากี่วัน

อีกตัวอย่างหนึ่ง เงิน 100 เป็น 121 ในสองปี มี CAGR 10% ไม่ใช่ 10.5% การหารผลตอบแทนรวมด้วยจำนวนปีไม่ใช่การคิดทบต้น

ดูด้วยว่าพอร์ตอยู่ต่ำกว่าจุดสูงสุดนานเท่าไร กำไรกระจุกตัวอยู่ช่วงไหน และผลแต่ละช่วงต่างกันอย่างไร หากผลสูงผิดสังเกต ให้ตรวจ timing, costs, ความยาวตัวอย่าง และจำนวนการลอง หลีกเลี่ยงเกณฑ์เหมารวมว่า “Sharpe เกินเลขหนึ่งต้องผิด” เพราะเลขเดียวไม่บอกที่มาของผลทั้งหมด [2, หน้า PDF 8–10; 3]

สร้างรายงานด้วย QuantStats

QuantStats มีส่วนคำนวณสถิติ วาดกราฟ และสร้าง HTML tear sheet โดยรับชุดผลตอบแทนเป็นข้อมูล จึงควรส่งผลตอบแทน สุทธิที่จัดเวลาไว้ถูกต้องแล้ว พร้อม benchmark ที่ตรงช่วงกัน

Win rate ของรายงานแบบ return series หมายถึงสัดส่วนช่วงเวลาที่ให้ผลบวก เช่น วันบวก ไม่จำเป็นต้องเท่ากับสัดส่วนรายการซื้อขายที่ชนะ หนึ่ง trade ที่ถือหลายวันอาจมีทั้งวันบวกและวันลบ [6]

Notebook หลักของบทนี้คำนวณด้วย Python standard library และรันได้โดยไม่ต้องใช้ QuantStats ตัวอย่างเสริมต่อไปนี้เป็นแนวทางเมื่อมี pandas และ quantstats ติดตั้งแล้ว ไม่ถูกเรียกใช้โดยหน้าเว็บ และไม่ได้ทดสอบการสร้างรายงาน QuantStats ในชุดตรวจบทนี้:

PYTHON
pythonคัดลอก
import jsonfrom pathlib import Pathimport pandas as pdimport quantstats as qs saved = json.loads(Path("backtest-intro-results.json").read_text())net = saved["results"][0]["returns"]  # causal fixed, net of assumed costs# Artificial dates for report formatting only; these are not market observations.index = pd.bdate_range("2000-01-03", periods=len(net))returns = pd.Series(net, index=index, name="Synthetic causal fixed")benchmark = pd.Series(saved["benchmark"]["returns"], index=index,                      name="Synthetic buy and hold")qs.reports.html(returns, benchmark=benchmark, output="backtest-report.html")

วันที่ในตัวอย่างเสริมถูกสร้างขึ้นเพื่อให้รายงานจัดรูปแบบได้เท่านั้น ไม่ใช่วันที่เกิดราคาจริง และไม่ได้แทนปฏิทินวันหยุดของตลาด

จุดที่ทำให้ผลดีเกินจริง

นอกจาก look-ahead ยังมีจุดที่ควรตรวจร่วมกัน:

  • Survivorship bias: เลือกเฉพาะสินทรัพย์ที่ยังอยู่ในปัจจุบัน แล้วลืมตัวที่ถูกถอดหรือหายไปในอดีต
  • Overfitting / selection bias: ลองหลายกฎ หลายช่วงข้อมูล หรือหลายวิธี clean แล้วแสดงเฉพาะผู้ชนะ โดยไม่บอกจำนวนการลอง
  • ข้อมูลไม่ตรงเวลาที่ใช้ได้จริง: ใช้ตัวเลขที่แก้ย้อนหลัง หรือถือว่างบการเงินพร้อมตั้งแต่วันที่สิ้นงวดแทนวันที่เปิดเผย
  • Execution ที่มองโลกดีเกินไป: สมมติซื้อได้ครบทุกครั้ง ไม่คิด spread, slippage, impact หรือข้อจำกัดการยืมหุ้น
  • Drawdown tolerance: ยอมรับความเสี่ยงบนกระดาษได้ แต่หยุดกลยุทธ์กลางทางเมื่อเจอการขาดทุนจริง ซึ่งทำให้เส้นทางใช้งานต่างจาก backtest

ดูรายละเอียดในเอกสาร [2, หน้า PDF 5–8; 3, หน้า 9–12; 4, หน้า PDF 15–17]

ฝึกอ่านผลและรันซ้ำ

ดาวน์โหลด Notebook ที่รันแล้ว · Python example · ข้อมูลสมมติ JSON · ผลคำนวณ JSON · Markdown บทนี้

Python example ใช้ standard library จึงไม่ต้องติดตั้ง package หรือเชื่อมต่ออินเทอร์เน็ต ตัว Notebook บรรจุโค้ดและตัวอย่างครบในตัว ใช้ Python 3 รันเซลล์จากบนลงล่างได้ ส่วนไฟล์ข้อมูลและผล JSON ใช้ตรวจเทียบกับห้องทดลองเว็บ

Terminal
shellคัดลอก
python3 lesson_13.py

ลองตอบก่อนดูคำอธิบายในแบบทบทวน:

  1. ถ้า signal ถูกเลื่อนแล้ว แต่ volatility ใช้ข้อมูลทั้งชุด การตัดสินใจยังมีข้อมูลอนาคตหรือไม่
  2. เมื่อเพิ่มต้นทุนจาก 5 เป็น 10 bps กรณีไหนได้รับผลกระทบมาก และ turnover ช่วยอธิบายได้แค่ไหน
  3. หาก targeting ลด drawdown แต่ลดผลตอบแทนด้วย ควรอ่าน metric ใดเพิ่มก่อนสรุปว่าดีกว่า
  4. ถ้าผลช่วงทดสอบไม่ผ่าน คุณจะตรวจขั้นตอนใดก่อน และจะบันทึกการเปลี่ยนแปลงอย่างไร
KNOWLEDGE CHECKข้อ 1 จาก 6
  1. 1ข้อ 1
  2. 2ข้อ 2
  3. 3ข้อ 3
  4. 4ข้อ 4
  5. 5ข้อ 5
  6. 6ข้อ 6
รู้ราคาปิด session t แล้วส่งสัญญาณกลับไปซื้อที่ราคาเปิด t มีปัญหาอะไร?
Look-ahead bias เพราะราคาปิดยังไม่พร้อม ณ เวลาเปิดไม่มีปัญหาหากกำไรน้อยกว่า benchmarkไม่มีปัญหาหากใช้ vectorized backtest
ตรวจคำตอบ

บันทึกผลก่อนทดลองรอบถัดไป

เก็บกฎ พารามิเตอร์ ช่วงข้อมูล และผลของรอบที่ไม่ผ่านไว้ด้วย หากจะแก้กฎ ให้เขียนเหตุผลและระบุว่าดูข้อมูลชุดใดไปแล้ว ก่อนเริ่มการประเมินครั้งถัดไป

แหล่งที่ใช้ในบทนี้

บทนี้เรียบเรียงและสร้างตัวอย่างใหม่จาก Resource ที่ให้มาเท่านั้น ตัวเลขในห้องทดลองเป็นข้อมูลสมมติที่คำนวณใหม่ ไม่มีผลตลาดจริงหรือข้อมูลราคาจากอินเทอร์เน็ต

  1. Yves Hilpisch, Python for Algorithmic Trading: From Idea to Cloud Deployment. ไฟล์ python for algorithmic trading book (js).pdf ที่แนบ: บท 4 หน้า PDF 75–101 โดยเฉพาะ lag หน้า 84 และต้นทุนหน้า 94; บท 6 หน้า 148–152; ตัววัดหน้า 278–279 เลขเหล่านี้เป็นหน้า 1-based ของไฟล์ PDF ที่สร้างผ่าน browser ไม่ใช่เลขหน้าฉบับพิมพ์
  2. Jacques Joubert, Dragan Sestovic, Illya Barziy, Walter Distaso และ Marcos Lopez de Prado, The Three Types of Backtests, เวอร์ชัน 29 July 2024, ไฟล์ three+types+of+backtests.pdf ที่แนบ: หน้า PDF 3–5 เรื่องประเภท, 5–8 เรื่องข้อผิดพลาด, 8–10 เรื่องตัววัด และ 16 เรื่องหน้าที่ของ backtest
  3. Rob Arnott, Campbell R. Harvey และ Harry Markowitz, A Backtesting Protocol in the Era of Machine Learning, 29 October 2018, ไฟล์ ssrn-3275654.pdf ที่แนบ: หน้า 8–12 เรื่องสมมติฐาน ข้อมูล และการทดสอบ; หน้า 14–16 เรื่องวัฒนธรรมวิจัยและข้อจำกัด
  4. Introduction to Backtesting, สไลด์ 19 หน้าในลิงก์ที่ให้: หน้า PDF 4–8 เรื่องแบ่งข้อมูลและนิยาม, 15–17 เรื่องข้อจำกัดและ bias
  5. Hudson Thames reading-group transcript ที่แนบและข้อความบรรยายที่ให้ในคำขอ, เรื่อง vectorized backtesting, signal lag, volatility targeting และ tear sheet ใช้เป็นเส้นเรื่องการเรียนรู้ โดยไม่ยกคำกล่าวเรื่องผลตอบแทนหรือเกณฑ์ Sharpe ตายตัวมาเป็นข้อเท็จจริงทั่วไป
  6. QuantStats repository, README ที่ลิงก์ให้มา ตรวจวันที่ 25 September 2026: การวิเคราะห์ return series, สถิติ กราฟ และ HTML tear sheet

ข้อความภาษาอังกฤษใน “หลักคิด: แก้กระบวนการวิจัย” คงตามข้อความที่กำหนดมา ไม่ระบุชื่อผู้กล่าวเพราะยังไม่ได้ยืนยันต้นทางคำต่อคำ ภาพที่แนบเป็นปกและคำรับรองหนังสือ Advances in Financial Machine Learning จึงไม่ใช้แทนหลักฐานว่าได้อ่านเนื้อหาหนังสือเล่มนั้น ไม่แจกจ่าย PDF ต้นฉบับหรือภาพจากหนังสือในชุดดาวน์โหลด

© 2023 by QuantCorner, Thailand.

bottom of page