walk-forward optimization ได้ชื่อว่าเป็นวิธีที่ซื่อสัตย์ที่สุดในการจูนกลยุทธ์ และมันก็สมควรได้ชื่อนั้น — อย่างน้อยก็เมื่อเทียบกับการจูนบนข้อมูลทั้งก้อนแล้วนั่งชื่นชมผลลัพธ์ของตัวเอง แต่เทคนิคนี้มีรูปแบบความล้มเหลวที่เกิดขึ้นอย่างเงียบ ๆ และทุกแบบให้ผลผลิตอย่างเดียวกัน คือรายงานผลตรวจสอบที่เขียนว่า "ทนทาน" เย็บติดอยู่กับกลยุทธ์ที่ไม่ทนทานเลย ต่อไปนี้คือสามแบบที่เราต้องออกแบบระบบมารับมือ จัดเรียงตามซากที่มันทิ้งไว้
ความล้มเหลวที่หนึ่ง: หน้าต่างข้อมูลรั่ว
วิธีที่ผิด: จูนด้วยข้อมูลมกราคม-มิถุนายน ตรวจสอบด้วยกรกฎาคม แล้วปล่อยให้อะไรก็ตามจากกรกฎาคมไหลย้อนไปมีอิทธิพลกับรอบที่สอง — รันใหม่หลังเห็นตัวเลข out-of-sample แล้ว, "ปรับนิดเดียว" ที่กริดพารามิเตอร์, ฟีเจอร์ที่ normalize บนอนุกรมทั้งเส้น แต่ละอย่างดูไร้พิษภัย แต่พอรวมกันมันเปลี่ยนหน้าต่าง out-of-sample ให้กลายเป็นข้อมูล in-sample แบบหน่วงเวลา
ซากที่เหลือไว้: Sharpe ของ out-of-sample ที่วิ่งตาม Sharpe ของ in-sample อย่างน่าพิศวง ผล out-of-sample ของจริงนั้นเต็มไปด้วยสัญญาณรบกวนและมักน่าผิดหวัง ถ้าความสัมพันธ์ IS/OOS ราบรื่นจนน่าสงสัย แปลว่ามีข้อมูลไหลย้อนกลับอยู่ เราจึงเฝ้าดูอัตราส่วนนี้อย่างชัดเจน — in-sample เกิน 3 เท่าของ out-of-sample จะติดธงทันที และ out-of-sample ที่เท่ากับหรือต่ำกว่าศูนย์ถือว่าตายสถานเดียว ไม่ว่า in-sample จะสวยแค่ไหน
ความล้มเหลวที่สอง: เลือกตัวชี้วัดข้ามหน้าต่างให้เข้าทางตัวเอง
รัน walk-forward สามหน้าต่าง ได้ผลที่เต็มไปด้วยสัญญาณรบกวนมาสามชุด แล้วก็สรุป: ใช้ Sharpe เฉลี่ยดี? หรือค่ามัธยฐาน? หรือตัดหน้าต่างที่แย่ที่สุดทิ้งเพราะ "regime เปลี่ยน"? ทุกทางเลือกคือองศาอิสระเพิ่มขึ้นหนึ่งขั้น และนักปรับค่าที่มุ่งมั่นพอ (ไม่ว่าจะเป็นมนุษย์หรือ Bayesian) ย่อมหาวิธีสรุปที่ทำให้กลยุทธ์นี้ดูดีที่สุดจนได้ 75 trials ของ Optuna ต่อหนึ่งหน้าต่าง คือ 75 โอกาสในการฟิตกับสัญญาณรบกวน คูณด้วยจำนวนวิธีสรุปที่คุณยอมเปิดใจให้
ซากที่เหลือไว้: กลยุทธ์ที่ผ่านการตรวจสอบ แล้วพอออกไปเทรดจริงกลับให้ผลเท่ากับหน้าต่างที่แย่ที่สุด เพราะหน้าต่างที่แย่ที่สุดคือหน้าต่างเดียวที่พูดความจริง กฎของเราคือ วิธีรวมผลถูกกำหนดไว้ในไฟล์คอนฟิกก่อนรัน งบจำนวน trial ถูกกำหนดตายตัว และนักวิเคราะห์ต้องอ่านผลแยกรายหน้าต่างพร้อมค่าการกระจาย กลยุทธ์ที่ต้องพึ่งวิธีสรุปแบบเอาใจถึงจะผ่าน ถือว่าไม่ผ่าน
ความล้มเหลวที่สาม: holdout ที่เลิกเป็น holdout ไปแล้ว
holdout ใช้ได้ครั้งเดียวเท่านั้น ครั้งที่สองที่กลยุทธ์ถูกนำมาวัดกับมัน — หลังจากขยับพารามิเตอร์นิดหน่อย ปรับสัญญาณหน่อยหนึ่ง หรือ "ขอเช็กอีกทีเฉย ๆ" — มันไม่ใช่ holdout อีกต่อไปแล้ว มันกลายเป็นชุดตรวจสอบแบบช้า ๆ ข้อมูล 15 วันที่ยังไม่ถูกแตะต้องฟังดูรักษาไว้ง่ายนิดเดียว จนกระทั่งแรงกดดันจากการทำซ้ำมาถึง แล้วการเช็กใหม่ก็ดูไม่เสียหายอะไรเลย
ซากที่เหลือไว้นั้นแนบเนียน: ผล holdout ที่ดีขึ้นเรื่อย ๆ ตามรอบการทำซ้ำของกลยุทธ์เดิม ข้อมูล out-of-sample ที่สดใหม่ไม่มีเหตุผลอะไรจะให้รางวัลกับรอบที่สามมากกว่ารอบที่หนึ่ง และเมื่อมันทำแบบนั้น แปลว่า holdout ถูกขุดไปแล้ว เราจึงบังคับหลักการยิงนัดเดียวด้วยกลไก: holdout ถูกประเมินหนึ่งครั้งต่อการรันไปป์ไลน์หนึ่งครั้ง ผลลัพธ์ถูกบันทึกลงประวัติ และกลยุทธ์ที่อยากลองใหม่ต้องกลับไปวิ่งผ่านด่านทั้งหมดอีกรอบ — รวมถึงหน้าต่างชุดใหม่ด้วย มันต้องรักษา Sharpe ไว้ได้อย่างน้อย 70% ของ out-of-sample จาก walk-forward และไม่มีการทอยลูกเต๋าลูกนั้นซ้ำอีกเป็นอันขาด
สัญญาณที่รอดพ้นทั้งสามแบบ
ก่อนจะไปถึงทั้งหมดนั้น เรารันการกวาดค่าความไวแบบตรงไปตรงมาก่อน: ขยับพารามิเตอร์แต่ละตัว ±20% แล้วดูว่าตัวชี้วัดเปลี่ยนไปอย่างไร เอดจ์ของจริงจะเสื่อมลงอย่างนุ่มนวล ส่วนความบังเอิญจะร่วงลงหน้าผา นี่คือการทดสอบที่ถูกที่สุดในไปป์ไลน์ และมันคว่ำกลยุทธ์ที่มิฉะนั้นคงล่องผ่านทุกอย่างข้างบนไปได้สบาย ๆ — เพราะหน้าผาพารามิเตอร์คือหน้าตาของ overfitting ก่อนที่คุณจะเปิดโอกาสให้มันไปหลบซ่อนอยู่ในกลไกการตรวจสอบ
ทั้งหมดนี้ไม่ได้ทำให้การปรับค่าพารามิเตอร์ปลอดภัย แต่มันทำให้ความล้มเหลวส่งเสียงดังพอให้ได้ยิน — ซึ่งเป็นสิ่งมากที่สุดที่คุณจะเรียกร้องจากกระบวนการตรวจสอบได้อย่างซื่อสัตย์
← บทความทั้งหมด