เวลา 10:07 น. ในวันอังคาร เอเจนต์วิจัยของเราพบจังหวะขาขึ้นระยะสั้นใน ETF ดัชนี สัญญาณจากสินทรัพย์อ้างอิงเป็นสัญญาณทั่วไป: ราคากลับขึ้นมายืนเหนือค่าเฉลี่ย 20 แท่ง ความผันผวนที่เกิดขึ้นจริงเริ่มลดลง และมีการประกาศข้อมูลเศรษฐกิจมหภาคตามกำหนดในเซสชันถัดไป กลยุทธ์เสนอให้เปิดคอลสเปรดที่มีเวลาถึงวันหมดอายุประมาณ 2 สัปดาห์
แบ็กเทสต์เห็นด้วย แต่กลยุทธ์จำลองไม่ได้ส่งคำสั่ง เมื่อเราเปรียบเทียบคำสั่งซื้อขาย เวลาประทับของสัญญาณตรงกัน และราคาสินทรัพย์อ้างอิงต่างกันเพียงไม่กี่เซนต์ แต่สัญญาที่เลือกกลับต่างกัน: แบ็กเทสต์ซื้อสัญญาที่หมดอายุวันศุกร์ซึ่งดูดีที่สุดในข้อมูลย้อนหลัง ส่วนกระบวนการจำลองเลือกวันหมดอายุถัดไปที่มีการจดทะเบียน ซึ่งช้ากว่า 1 สัปดาห์
ความคลาดเคลื่อนนี้เกิดจากการเชื่อมข้อมูลปฏิทิน เรามองว่า “จำนวนวันจนถึงวันหมดอายุ” เป็นคุณสมบัติของวันที่ แล้วเลือกสัญญาที่วันหมดอายุใกล้กับวันที่เป้าหมายที่สุด ในข้อมูลย้อนหลัง ปฏิทินวันหมดอายุมีรายการรายสัปดาห์ที่เพิ่งเพิ่มเข้ามาหลังวันที่เรากำลังทดสอบ แบ็กเทสต์จึงใช้สัญญาจากอนาคต โดยดูเผิน ๆ เหมือนเป็นแค่ทางลัดที่ไม่เป็นอันตราย
ตอนแรกเราสงสัยว่ามีบั๊กเขตเวลา วันหมดอายุออปชันเป็นจุดที่ทำให้เกิดบั๊กแบบนี้ได้ง่ายเป็นพิเศษ: เซสชันตลาดสิ้นสุดตามเวลานิวยอร์ก เวลาประทับจากตลาดหลักทรัพย์อาจจัดเก็บเป็น UTC และวันที่ที่เวลาเที่ยงคืนอาจเลื่อนไปอีกวันเมื่อไปป์ไลน์แปลงข้อมูลอย่างไม่ระมัดระวัง เราตรวจสอบแล้ว เวลาประทับถูกต้อง ปัญหาคือในวันอังคารนั้น สัญญาดังกล่าวยังไม่มีอยู่ในจักรวาลข้อมูลย้อนหลัง
บทเรียนแรกคือ ข้อมูลออปชันย้อนหลังต้องมีชุดสัญญาที่จดทะเบียน ณ เวลานั้น วันหมดอายุของสัญญาบอกคุณว่าสัญญาสิ้นสุดเมื่อใด แต่ไม่ได้บอกว่าจดทะเบียนเมื่อใด เริ่มซื้อขายได้เมื่อใด หรือระบบของคุณจะเลือกสัญญานั้นได้หรือไม่ในเวลานั้น
เราสร้างขั้นตอนการเลือกใหม่โดยอิงข้อมูลที่มีอยู่ ณ เวลาตัดสินใจ สำหรับสัญญาที่เข้าข่ายทุกสัญญา เรากำหนดให้เวลาจดทะเบียนต้องไม่เกินเวลาตัดสินใจ ต้องมีราคาเสนอซื้อขายที่ยังไม่เก่าเกินเกณฑ์ความสดของข้อมูล และต้องอยู่ในเซสชันตลาดที่กลยุทธ์ส่งคำสั่งได้ เรายังบันทึกชุดสัญญาที่เข้าข่ายก่อนจัดอันดับด้วย จุดสุดท้ายนี้สำคัญ เพราะแบ็กเทสต์เดิมเก็บไว้แค่สัญญาที่ชนะ เราจึงบอกไม่ได้ว่าแบ็กเทสต์เปรียบเทียบสัญญาที่เข้าเกณฑ์ 5 สัญญา หรือแอบเลือกจากปฏิทินที่ยังมาไม่ถึง
ขั้นต่อมา เราตรวจสอบราคาเสนอซื้อขายที่ใช้กำหนดราคาสเปรด แบ็กเทสต์เลือกใช้ราคาเสนอซื้อขายล่าสุดของแต่ละขาแยกจากกัน ราคาเสนอขายของคอลมาจากเวลา 10:06:58 ส่วนราคาเสนอซื้อของคอลที่ขายชอร์ตมาจากเวลา 10:04:11 ทั้งคู่ยังถือว่าใหม่ตามนโยบายข้อมูลที่ค่อนข้างกว้าง แต่ตลาดเคลื่อนไหวไปแล้วระหว่างสองเวลานั้น ราคากลางของสเปรดที่คำนวณจากขาที่มีเวลาต่างกันอาจสะท้อนตลาดที่ไม่เคยเกิดขึ้นจริง
เราแก้กฎราคาเสนอซื้อขายให้เวลาประทับของทั้งสองขาต่างกันได้ไม่เกิน 2 วินาที และตัดตลาดที่ราคาไขว้กันหรือมีขนาดเป็นศูนย์ออก ทำให้จำนวนข้อมูลย้อนหลังที่ใช้ได้ลดลง แต่ราคาที่เหลือก็น่าเชื่อถือขึ้น เมื่อไม่มีราคาเสนอซื้อขายที่ซิงโครไนซ์กัน เราจะระบุว่าสัญญานั้นใช้ไม่ได้ แทนที่จะเติมช่องว่างด้วยราคาเก่า
จากนั้นก็มาถึงกฎการจัดอันดับ เอเจนต์เลือกวันหมดอายุที่มีต้นทุนสเปรดตามราคาเสนอซื้อขายต่ำที่สุด ฟังดูสมเหตุสมผล จนกว่าสเปรดนั้นจะมีสัญญาแสดงอยู่เพียง 1 สัญญาและราคาเสนอซื้อขายก็เก่า เรากำหนดเป้าหมายให้ชัดเจน: เพิ่มผลตอบแทนคาดหวังต่อหน่วยความเสี่ยงที่กำหนดไว้ให้สูงสุด โดยพิจารณาเฉพาะสัญญาที่ผ่านเกณฑ์ขั้นต่ำด้านขนาดราคาเสนอซื้อขาย ความสดของข้อมูล และการจดทะเบียน ในตัวอย่างนี้ วันหมดอายุที่ใกล้ที่สุดและเข้าเกณฑ์มีส่วนต่างราคาเสนอซื้อขายระหว่างสองขาอยู่ที่ $0.42 ส่วนวันหมดอายุที่ช้ากว่ามีส่วนต่าง $0.31 ตัวเลือกที่ดูเหมือนถูกกว่านั้นมีสัญญาแสดงอยู่ที่ขาชอร์ตเพียง 1 สัญญา
| สัญญาที่พิจารณา | วันหมดอายุมีให้เลือกในเวลานั้นหรือไม่ | อายุของราคาเสนอซื้อขาย | ขนาดที่แสดงของขาชอร์ต | การตัดสินใจ |
|---|---|---|---|---|
| วันศุกร์รายสัปดาห์ | ไม่มี | ไม่เกี่ยวข้อง | ไม่เกี่ยวข้อง | ตัดออก |
| วันศุกร์ถัดไป | มี | 1.4 วินาที | 18 สัญญา | เข้าเกณฑ์ |
| วันศุกร์ที่สามของเดือน | มี | 9.8 วินาที | 1 สัญญา | ตัดออกเพราะราคาเก่าและสภาพคล่องบาง |
เราจำลองเหตุการณ์นี้ซ้ำโดยใช้กฎดังกล่าว ตอนนี้แบ็กเทสต์เลือกวันหมดอายุเดียวกับกลยุทธ์จำลอง และบันทึกเหตุผลที่ตัดสัญญาอื่นออก ราคาที่เปิดสเปรดได้แย่กว่าราคาเดิมที่แบ็กเทสต์บันทึกไว้ $0.11 นั่นไม่ได้แปลว่ากลยุทธ์ไม่มีมูลค่า แต่หมายความว่าตัวเลขผลการดำเนินงานเดิมรวมการเลือกสัญญาที่กระบวนการจริงทำซ้ำไม่ได้ไว้ด้วย
มีเรื่องกวนใจเล็กน้อย: รูปแบบสัญลักษณ์ของตลาดหลักทรัพย์ทำให้บั๊กวันหมดอายุดูเหมือนปัญหาคุณภาพข้อมูล เราพบรหัสรายสัปดาห์ของผู้ให้บริการข้อมูลรายหนึ่งที่ต่างจากรหัสรายเดือนเพียง 1 อักขระ ผมยังคงเก็บสัญลักษณ์ดิบไว้ข้างคีย์สัญญาที่ปรับให้อยู่ในรูปแบบมาตรฐานในบันทึกตรวจสอบ แม้จะไม่สวยงามนัก แต่วิธีนี้ช่วยให้เราไม่รีบเชื่อการเชื่อมข้อมูลที่ดูเรียบร้อยเกินไป
หากคุณกำลังสร้างแบ็กเทสต์ออปชัน ให้บันทึกชุดสัญญาที่พิจารณาทั้งหมด ณ ทุกจุดตัดสินใจ พร้อมสถานะการจดทะเบียน เวลาประทับของราคาเสนอซื้อขาย ขนาด และเหตุผลที่ตัดสัญญาแต่ละรายการออก จากนั้นทำให้การเลือกสัญญาเป็นฟังก์ชันที่กำหนดผลลัพธ์ได้แน่นอนจากภาพข้อมูลชุดนั้น การเลือกวันหมดอายุเป็นส่วนหนึ่งของกลยุทธ์ หากแบ็กเทสต์มองเห็นสัญญาที่กลยุทธ์จำลองมองไม่เห็น การเปรียบเทียบสัญญาณก็เริ่มต้นหลังจากคำตอบเปลี่ยนไปแล้ว
← บทความทั้งหมด


