เมื่อเดือนที่แล้ว มีเส้น equity จากกลยุทธ์ที่สร้างขึ้นมาเส้นหนึ่ง ซึ่งมี drawdown อยู่ที่ 63% ลึกและหนักหน่วง ก่อนจะฟื้นกลับมาอย่างสวยงามใน 6 สัปดาห์ถัดมา เป็นรูปแบบที่นักวิจัยมองแล้วคิดว่ายังพอรับไหวถ้าลดขนาดสถานะลง ผมนำมันไปรันใหม่ผ่านระบบมาร์จินที่รู้จักระดับ maintenance margin แล้ว บัญชีถูกล้างพอร์ตในวันที่ 41 กลางช่วง drawdown พอดี และทุกอย่างหลังวันที่ 41 เป็นเรื่องแต่ง
นี่คือบั๊กแบ็กเทสต์ประเภทที่สร้างความเสียหายแพงที่สุดเท่าที่ผมรู้จัก เพราะมันไม่ได้ทำให้ผลตอบแทนเพี้ยนไปไม่กี่ basis points แต่มันลบสถานะที่เมื่อเกิดแล้วจะย้อนกลับไม่ได้ออกจากการจำลอง กลยุทธ์ที่อาจหมดตัวได้กับกลยุทธ์ที่หมดตัวไม่ได้ เป็นคนละกลยุทธ์กัน และแบ็กเทสต์ที่ไม่เคยตรวจมาร์จินก็บอกคุณไม่ได้ว่ากำลังใช้แบบไหน
ผมเห็นคนทำผิดอยู่ 3 วิธี
วิธีผิดข้อ 1: ใช้เลเวอเรจเป็นตัวเลขคูณผลตอบแทน
นี่คือรูปแบบที่พบบ่อยที่สุด คุณคำนวณอนุกรมผลตอบแทนจากสัญญาณ แล้วตัดสินใจว่าจะใช้เลเวอเรจ 10x จากนั้นก็คูณเข้าไป บางครั้งทำซับซ้อนขึ้นเล็กน้อย โดยกำหนดขนาดสถานะเป็น equity * leverage / price แต่สถานะบัญชีก็ยังเป็นเพียงตัวเลขตัวเดียวที่ขึ้นลง ไม่มีมาร์จินคงเหลือ ไม่มีเพดาน notional และไม่มีเงื่อนไขล้มเหลว
ความเสียหายแฝงอยู่แนบเนียน ซึ่งเป็นเหตุผลที่มันรอดจากการรีวิวได้ Sharpe ไม่เปลี่ยนตามสเกล ดังนั้นตัวเลขพาดหัวของคุณจึงไม่ขยับเมื่อเปลี่ยนเลเวอเรจจาก 3x เป็น 30x นักวิจัยจึงสรุปว่าเลเวอเรจเป็นปุ่มปรับฟรีที่แลกความผันผวนกับผลตอบแทนได้ ส่วน max drawdown จะเพิ่มตามสัดส่วนและยังต่ำกว่า 100% ด้วยความบังเอิญทางคณิตศาสตร์ เพราะอนุกรมผลตอบแทนที่ถูกคูณเข้าไปจะเข้าใกล้ศูนย์แบบลู่เข้า แต่ไม่ข้ามศูนย์ เมื่อนำวันติดลบ -9% ไปคูณ 12 แบบจำลองที่ตรงไปตรงมาจะได้ -108% ส่วนแบบง่ายจะได้ “-108% แต่เส้น equity ยังเป็นบวก” ทั้งนี้ขึ้นอยู่กับว่าคุณทบต้นหรือบวกผลตอบแทน ผมเห็นมาทั้ง 2 แบบ
สิ่งที่ขาดไปคือ เลเวอเรจไม่ได้ถูกนำไปใช้กับผลตอบแทนของคุณ แต่ใช้กับ หลักประกัน ของคุณ และหลักประกันมีจำนวนจำกัด ซึ่งแพลตฟอร์มคอยตรวจสอบทุกวินาที เมื่อมันลดต่ำกว่าข้อกำหนด maintenance margin สถานะก็ไม่ใช่ของคุณอีกต่อไป
สัญญาณบอกเหตุ: ถ้าการจำลองของคุณทำให้ขาดทุนทั้งหมดไม่ได้ไม่ว่าจะใช้เลเวอเรจเท่าไร แสดงว่ามันไม่ได้จำลองเลเวอเรจ
วิธีผิดข้อ 2: คำนวณราคาล้างพอร์ตจากเลเวอเรจอย่างเดียว
ขั้นถัดมาของความซับซ้อนคือเพิ่มการตรวจล้างพอร์ต โดยทั่วไปจะทำประมาณนี้: ที่ 20x การเคลื่อนไหวสวนทาง 5% จะล้างมาร์จิน จึงล้างพอร์ตที่ราคาเข้า × 0.95 สำหรับสถานะ Long ดูเรียบง่าย เข้าใจง่าย และผิดพลาดพร้อมกันถึง 4 ทาง
แพลตฟอร์ม perp ไม่ได้ใช้การตั้งค่าเลเวอเรจของคุณตัดสินว่าถึงจุดจบเมื่อไร แต่ใช้ maintenance margin rate ที่เพิ่มขึ้นตาม notional ของสถานะ โดยอิงตารางระดับ ตัวอย่างโครงสร้างโดยประมาณของ BTCUSDT USDⓈ-M ซึ่งเปลี่ยนได้เมื่อแพลตฟอร์มปรับปรุงตาราง:
| Notional ของสถานะ (USDT) | อัตรา maintenance margin | เลเวอเรจสูงสุด |
|---|---|---|
| 0 – 50,000 | 0.40% | 125x |
| 50,000 – 600,000 | 0.50% | 100x |
| 600,000 – 3,000,000 | 1.00% | 50x |
| 3,000,000 – 12,000,000 | 2.50% | 20x |
| 12,000,000 – 70,000,000 | 5.00% | 10x |
ดังนั้น การเคลื่อนไหวสวนทางที่สถานะ Long แบบ isolated รับไหวโดยประมาณคือ 1/L − MMR ไม่ใช่ 1/L ที่ 20x ในระดับที่ 2 จะเท่ากับ 5% − 0.5% = 4.5% ครึ่งเปอร์เซ็นต์ฟังดูเหมือนแค่การปัดเศษ แต่สำหรับ BTC ที่ราคา 84,000 คือส่วนต่างราคา 420 ดอลลาร์ และในชั่วโมงที่ผันผวนรุนแรง 420 ดอลลาร์คือความต่างระหว่างการโดนไส้เทียนกวาดออกจากสถานะกับการรอดไปได้ ไส้เทียนแต่ละแท่งเหมือนโยนเหรียญ และคุณก็เอนโอกาสให้เข้าข้างตัวเองทั้งหมด
แล้วก็ยังมีค่าธรรมเนียม ค่าธรรมเนียม taker ตอนเข้าออเดอร์ถูกหักจากมาร์จินทันทีที่ออเดอร์จับคู่: ค่าธรรมเนียม 0.045% ของ notional 500,000 เท่ากับ 225 USDT ที่หักจากมาร์จินคงเหลือ 25,000 ซึ่งทำให้ราคาล้างพอร์ตขยับก่อนที่สถานะจะทำอะไรเสียอีก Funding ก็ทำแบบเดียวกันอย่างต่อเนื่อง และเมื่อคิดจาก notional ที่ใช้เลเวอเรจแล้ว ตัวเลขจะสูงกว่าที่นักวิจัยคาดไว้มาก:
สถานะที่ไม่ทำอะไรเลยเป็นเวลา 30 วัน — ไม่มีการเคลื่อนไหวสวนทาง ไม่มีการเทรด — จะสูญเสียหลักประกันไปเกือบ 1 ใน 5 และทำให้ราคาล้างพอร์ตขยับเข้ามาใกล้อย่างมีนัยสำคัญ ส่วนความผิดพลาดอีก 2 ทางคือระดับเปลี่ยนเมื่อคุณเพิ่มสถานะ ดังนั้นสถานะที่เริ่มในระดับ 0.5% แล้วถูกถัวเพิ่มจนเข้าไปอยู่ระดับ 1.0% จะมีราคาล้างพอร์ตแย่กว่าราคาที่คำนวณไว้ตอนเข้า และ cross margin จะรวมหลักประกันของหลายสถานะเข้าด้วยกัน การอยู่รอดของสถานะ Long BTC จึงขึ้นอยู่กับว่า Short ETH ของคุณกำลังเป็นอย่างไร ถ้าคุณจำลอง cross margin เป็นชุดสถานะ isolated ที่แยกจากกัน คุณกำลังจำลองโครงสร้างความสัมพันธ์ของบัญชีตัวเองกลับด้าน
วิธีผิดข้อ 3: จัดการการล้างพอร์ตด้วยราคาผิด จังหวะผิด และราคาเติมเต็มผิด
สมมติว่าคุณตั้งระดับทริกเกอร์ได้ถูกต้องแล้ว แล้วต่อไปล่ะ: ราคาไหนเป็นตัวข้ามระดับนั้น คุณตรวจเมื่อไร และออเดอร์ของคุณจะถูกเติมเต็มที่ราคาไหน?
การล้างพอร์ตทริกเกอร์ด้วย ราคา Mark ซึ่งเป็นดัชนีจากแพลตฟอร์ม Spot หลายแห่งที่มีองค์ประกอบ basis แบบปรับให้เรียบ เพื่อตั้งใจป้องกันไส้เทียนจากแพลตฟอร์มเดียว ส่วน Stop-loss ของคุณน่าจะทริกเกอร์ด้วยราคาซื้อขายล่าสุด ขึ้นอยู่กับการตั้งค่า ราคาทั้ง 2 แบบนี้จะไม่ตรงกันในจังหวะที่สำคัญที่สุด ระหว่างการร่วงต่อเนื่อง ราคาซื้อขายล่าสุดของ perp อาจหลุดต่ำกว่าราคา Mark 1–2% นานหลายสิบวินาที แบ็กเทสต์ที่ใช้ราคาต่ำสุดของ OHLCV เดียวกันตรวจทั้ง Stop และการล้างพอร์ตกำลังจำลองแพลตฟอร์มที่ไม่มีอยู่จริง
ข้อผิดพลาดทั้ง 2 แบบเกิดขึ้นได้จริงและไม่ได้หักล้างกัน ถ้าใช้ราคาซื้อขายล่าสุด คุณจะถูกล้างพอร์ตจากไส้เทียนที่แพลตฟอร์มมองข้าม ถ้าใช้ราคา Mark คุณอาจพลาดกรณีที่ตัวราคา Mark เองขยับ การที่ดัชนีเบี่ยงเบนจากราคาในแพลตฟอร์ม Spot เป็นสาเหตุจริงที่ทำให้ถูกล้างพอร์ตได้ที่ราคาซึ่งไม่เคยปรากฏบน perp ที่คุณเทรด
ต่อมาคือราคาเติมเต็ม ระบบแบบง่ายจะปิดสถานะที่ราคาล้างพอร์ต แล้วบันทึกผลขาดทุนเหมือนกับเป็น Stop แต่สิ่งที่เกิดขึ้นจริงคือสถานะจะถูกส่งต่อให้ระบบล้างพอร์ตที่ ราคา Bankruptcy ซึ่งเป็นระดับที่มาร์จินของคุณเหลือศูนย์พอดี และแย่กว่าระดับทริกเกอร์ พร้อมถูกเรียกเก็บค่าธรรมเนียมการปิดสถานะจากการล้างพอร์ตเพิ่มเติมตามระดับ โดยระดับล่างอยู่แถว ๆ 1% ของ notional ที่ 20x ค่าธรรมเนียม 1% ของ notional เท่ากับ 20% ของมาร์จินที่เหลือ หากระบบเติมเต็มออเดอร์ต่ำกว่าราคา Bankruptcy กองทุนประกันจะชดเชยส่วนต่าง แต่บางแพลตฟอร์ม หากกองทุนหมด ความเสียหายที่กระจายไปยังผู้ใช้จะลามไปถึงฝั่งที่ทำกำไรด้วย ผลขาดทุนจริงของคุณไม่ได้เท่ากับ drawdown จนถึงราคาล้างพอร์ต แต่จะมากกว่านั้น และส่วนเกินจะมากที่สุดในวันที่สมุดคำสั่งบางจนทำให้ผลกระทบรุนแรงที่สุด
คำถามเรื่องจังหวะเวลาจากกลไกภายในแท่งก็ใช้กับกรณีนี้เช่นกัน แต่ผลกระทบรุนแรงกว่าเดิม หากแท่ง 1 นาทีมีทั้งระดับ Take-profit และระดับล้างพอร์ต แบ็กเทสต์ที่ตรวจทางออกก่อนตรวจมาร์จินก็จะบันทึกกำไรอย่างสบายใจ แต่แพลตฟอร์มตรวจมาร์จินทุกครั้งที่ราคา Mark อัปเดต โดยประมาณวินาทีละครั้ง และทำก่อนสิ่งอื่นทั้งหมดที่คุณอาจอยากให้เกิดขึ้น
สิ่งที่ระบบต้องติดตามแทน
เรื่องพวกนี้ไม่จำเป็นต้องซับซ้อนพิสดาร แต่ต้องเก็บสถานะ บัญชีเป็นออบเจ็กต์ที่มี balance ไม่ใช่อนุกรมผลตอบแทน และในแต่ละแท่งต้องอัปเดตตามลำดับที่แพลตฟอร์มจะใช้:
- ยอดคงเหลือใน Wallet และ PnL ที่ยังไม่รับรู้ แยกจากกัน อัตราส่วนมาร์จินคือ maintenance margin หารด้วย margin balance และ margin balance รวม PnL ที่ยังไม่รับรู้ไว้ด้วย การเอาค่าสองอย่างนี้มาปนกันทำให้สถานะที่ขาดทุนดูเหมือนมีหลักประกันมากกว่าความเป็นจริง
- ตารางระดับของทุกสัญลักษณ์ พร้อมระบุวันที่เวอร์ชัน ตารางระดับมีการปรับปรุง แบ็กเทสต์ปี 2023 ที่ใช้ระดับของปี 2026 เป็นการแอบใช้ข้อมูลอนาคตอย่างแนบเนียน ซึ่งมักทำให้ผลดูดีขึ้น เพราะโดยทั่วไปแพลตฟอร์มผ่อนคลายข้อกำหนดของเหรียญหลักลงเมื่อเวลาผ่านไป
- อนุกรมราคา Mark ไม่ใช่แค่ Kline หากคุณหาแหล่งข้อมูลย้อนหลังของราคา Mark ไม่ได้ ให้ระบุไว้ในผลลัพธ์และใช้ค่าประมาณแบบเผื่อความเสี่ยง ห้ามแทนด้วยราคาซื้อขายล่าสุดโดยไม่บอก
- ตรวจมาร์จินเป็นลำดับแรกในการจัดเรียงเหตุการณ์ของแท่ง ก่อน Stop, เป้าหมาย, สัญญาณ หรือการปรับสมดุลพอร์ต
- การเติมเต็มที่ราคา Bankruptcy พร้อมค่าธรรมเนียมการปิดสถานะ โดยอ่านอัตราค่าธรรมเนียมจากแถวระดับเดียวกับ MMR
- สถานะปลายทางที่ย้อนกลับไม่ได้ เมื่อ equity แตะศูนย์ การรันก็จบ ไม่มีการตั้งต้นใหม่ ไม่มีการ “สมมติว่าเทรดเดอร์เติมเงิน” และไม่มีการรันอนุกรมต่อด้วย notional ก้อนใหม่
ข้อสุดท้ายนี่แหละที่ทำให้เกิดการโต้เถียงมากที่สุด มักมีคนชี้ว่าโต๊ะเทรดจริงสามารถฝากหลักประกันเพิ่มได้ การจบการจำลองจึงเข้มงวดเกินจริง อาจจะใช่ แต่คำกล่าวที่ว่า “กลยุทธ์นี้ใช้ได้ถ้าคุณคอยเติมเงินหลังจากมันล้างพอร์ต” ควรพูดออกมาตรง ๆ และทดสอบอย่างตั้งใจ โดยใส่การเติมเงินเป็นอินพุตที่ระบุชัดเจน แทนที่จะสอดแทรกเข้ามาเป็นค่าเริ่มต้น พอเขียนมันออกมาตรง ๆ คนส่วนใหญ่ก็พบว่าตัวเองไม่ได้หมายความอย่างนั้น
ประโยชน์ในทางปฏิบัติคือ เมื่อคุณรันกลยุทธ์เดียวกันบนระบบจำลองเทียบกับแพลตฟอร์มจริง อัตราส่วนมาร์จินที่แพลตฟอร์มรายงานกับค่าที่ Simulator คำนวณควรเคลื่อนไหวสอดคล้องกันภายใน 1 หรือ 2 basis points ตลอดทั้งวัน ตรวจสอบข้อตกลงนี้ได้ทุกนาทีในทุกสถานะที่เปิดอยู่โดยไม่มีค่าใช้จ่าย นี่คือการทดสอบ parity ที่ถูกที่สุดในทั้งระบบ แต่แทบไม่มีใครทำ และเมื่อค่าทั้ง 2 เริ่มคลาดกัน แพลตฟอร์มคือฝ่ายที่ถูก ส่วนคุณมีบั๊กที่ควรหาให้เจอก่อนที่ drawdown จะเป็นคนหาให้
← บทความทั้งหมด


