High-Performance Backtest Engines
How to build a backtest engine that runs hundreds of times faster without changing a single PnL number — data layout, caching, adaptive resolution, and architecture, from first speedups to production internals.
- 01
Jun 26, 2026 #algotradingบันไดความเร็วของ Backtest Engine: 298x บน CPU แล็ปท็อป, PnL เหมือนเดิมทุกประการจนถึง Trade สุดท้าย
ห้า implementation ของ parameter sweep 80 combo ชุดเดียวกัน ทุกตัวตรวจสอบแล้วว่าให้ PnL เหมือนกันทุกประการ: pandas rolling.apply ใช้เวลา 69.9 วินาที, numpy 3.1, numba 2.0, parallel numba 0.23 — ความเร็วที่วัดได้จริงเพิ่มขึ้น 298x บน Apple M2 Max โดยไม่เปลี่ยนฮาร์ดแวร์เลย และยังเร็วกว่า baseline แบบ vectorized ที่ทำได้ดีอยู่แล้วประมาณ 13x แต่ละขั้นบันไดให้อะไรบ้าง ทำไม GPU ไม่ใช่ชิ้นส่วนที่ขาดหายไป และคอขวดที่แท้จริงของการค้นหาพารามิเตอร์จำนวนมากอยู่ที่ไหน
- 02
Jul 2, 2026 #algotradingภาษีของเฟรมเวิร์ก: เมื่อไลบรารี Backtest ของคุณช้ากว่าลูป Pandas แบบง่ายๆ
เราทำเบนช์มาร์กเอนจิน backtest แปดตัวบน parameter sweep ชุดเดียวกัน — 150,000 แท่งราคา, 80 คอมโบ HMA-cross, ล็อกจำนวนเทรดให้ตรงกันที่ 2707 รายการ เฟรมเวิร์ก event-driven ที่ได้รับความนิยมมากที่สุดสองตัวกลับช้ากว่าลูป pandas ที่เขียนขึ้นมาเอง ในขณะที่เอนจินแบบ vectorized/compiled ทำงานเดียวกันได้เร็วกว่าประมาณ 13,000 เท่า การศึกษาต้นทุนแฝงต่อแท่งราคาที่ไลบรารียอดนิยมไม่เคยถูกออกแบบมาให้ตัดจ่ายได้
- 03
Mar 16, 2026 #algotradingAggregated Parquet Cache: วิธีเร่งความเร็วแบ็คเทสต์หลาย Timeframe ได้หลายร้อยเท่า
วิธีคำนวณ timeframe และ indicator ล่วงหน้าจากแท่งเทียนรายนาที บันทึกลง parquet และนำมาใช้สำหรับการทดสอบกลยุทธ์จำนวนมากโดยไม่ต้องคำนวณซ้ำซ้อน
- 04
Jul 3, 2026 #อัลโกเทรดดิ้งพื้นที่พารามิเตอร์สองแกน: ทำไมการสวีปส่วนใหญ่ของคุณจึงควรแทบจะฟรี
พารามิเตอร์แต่ละตัวมีต้นทุนการค้นหาไม่เท่ากัน พารามิเตอร์ของกลยุทธ์แยกออกเป็นแกนราคาแพง (อินดิเคเตอร์ — ต้องคำนวณใหม่ตลอดทั้งซีรีส์ราคา) และแกนราคาถูก (ค่าเกณฑ์ตัดสินใจ — การกวาด O(n) รอบเดียวบนสัญญาณที่คำนวณล่วงหน้า) เพราะอินดิเคเตอร์ไม่แปรผันต่อค่าเกณฑ์ คุณจึงคำนวณมันครั้งเดียวแล้วสวีปคอนฟิกค่าเกณฑ์นับพันที่ ~5,600 cfg/s — ถูกกว่าการคำนวณใหม่ต่อคอนฟิกราว 1,600 เท่า นี่คือการตีราคาคำสาปแห่งมิติเสียใหม่
- 05
Mar 17, 2026 #algotradingAdaptive Drill-Down: แบ็คเทสต์ด้วยความละเอียดข้อมูลแบบยืดหยุ่น ตั้งแต่นาทีจนถึงการเทรดดิบ
วิธีที่ความละเอียดข้อมูลแบบปรับตัวได้ช่วยเร่งความเร็วแบ็คเทสต์และประหยัดพื้นที่จัดเก็บ: drill-down จาก 1m ลงสู่ 1s, 100ms และการเทรดดิบ เฉพาะในจุดที่ราคาเคลื่อนไหวอย่างมีนัยสำคัญหรือปริมาณการซื้อขายพุ่งสูง ไม่ใช่ตลอดทั้งชุดข้อมูลประวัติศาสตร์
- 06
Jul 5, 2026 #algotradingประตูความเที่ยงตรง (Fidelity Gate): การทดสอบย้อนหลังแบบหยาบไปละเอียดจะหลอกคุณได้เร็วขึ้น เว้นแต่ตัวแทนราคาถูกจะจัดอันดับเหมือนกับตัวเต็มราคาแพง
การค้นหาแบบ drill-down / multi-fidelity (ASHA, successive halving, Hyperband) คัดกรองค่าคอนฟิกหลายพันแบบด้วยต้นทุนต่ำ และเลื่อนขั้นเฉพาะผู้รอดชีวิตไปสู่การประเมินเต็มรูปแบบที่มีราคาแพง มันคือการเร่งความเร็วที่แท้จริง แต่มันจะพังลงอย่างเงียบๆ หากการจัดอันดับที่ความเที่ยงตรงต่ำไม่สอดคล้องกับการจัดอันดับที่ความเที่ยงตรงสูง เราวัดค่าสหสัมพันธ์อันดับระหว่างโฟลด์ (fold-rank correlation) พบว่าที่หนึ่งโฟลด์ ค่า Spearman ρ อาจอยู่ที่ 0.03 (จัดอันดับแทบจะสุ่ม) แล้วไต่ขึ้นไปที่ 0.43, 0.67, 0.78, 0.91 เมื่อจำนวนโฟลด์เพิ่มขึ้น ทางแก้คือประตูบังคับหนึ่งด่าน นั่นคือวัดค่า ρ(ราคาถูก, เต็มรูปแบบ) ก่อน แล้วปรับความเที่ยงตรงขั้นต่ำขึ้นโดยอัตโนมัติไปยังขั้นแรกที่ ρ ≥ 0.5
- 07
Jul 4, 2026 #การเทรดอัลกอริทึมRandom Search กับ Smart Search: จุดตัดอยู่ที่ต้นทุนการประเมิน ไม่ใช่ตัวอัลกอริทึม
เมื่อ backtest หนึ่งครั้งมีต้นทุนต่ำ Sobol แบบ scrambled ที่โง่ ๆ จะชนะด้วย throughput ดิบ — smart sampler (TPE, CMA-ES, ASHA) ต้องจ่าย ask/tell tax ใน Python ที่ทำให้ช้าลง 20 เท่า จึงประเมินจุดได้น้อยกว่ามากเมื่อ wall-clock เท่ากัน และแพ้ไป แต่ถ้าทำให้แต่ละ eval มีต้นทุนสูงขึ้น (multi-TF + walk-forward fold) จุดตัดก็จะพลิกกลับ เราวัดทั้งสองระบอบ และเหตุใด fold-rank fidelity (ρ@1 เพิ่มจาก 0.03→0.43) จึงเป็นเงื่อนไขที่ต้องมีก่อนที่ pruning จะให้ผลตอบแทนคุ้มค่า
- 08
Jul 6, 2026 #algotradingกับดักความแม่นยำของ GPU: เมื่อ Backtest แบบ fp32 บน Apple Metal คืนค่าขยะออกมาอย่างเงียบๆ
GPU Metal ของ Apple ไม่มี float64 เลย หากพอร์ต backtest แบบ vectorized ไปใช้อย่างไม่ระวัง สูตร WMA แบบ prefix-sum ที่ดูน่าใช้ที่สุดจะทำให้ fp32 overflow — ค่าความคลาดเคลื่อนสัมพัทธ์สูงสุดถึง 211 เท่า — แต่โปรแกรมก็ยังรันจบและคืนตัวเลขที่ดูสมเหตุสมผลออกมา ทางแก้ไม่ใช่การเพิ่มความแม่นยำ แต่คือการเปลี่ยนสูตรคำนวณ: ใช้ windowed convolution โดยตรง ซึ่งปลอดภัยกับ fp32 ถึงระดับ 8×10⁻⁷ และเร็วกว่า numba แบบ single-thread ถึง 55.9 เท่า กับดักนี้ หลักคณิตศาสตร์เบื้องหลัง และวิธีพิสูจน์ว่าคุณไม่ได้ตกหลุมพราง
- 09
Jul 7, 2026 #algotradingเมื่อ GPU คุ้มค่าจริง: Roofline ของการ Sweep พารามิเตอร์ ที่ตัวเลขพาดหัว 167x แท้จริงคือ 27x อัลกอริทึม คูณ 6.2x ฮาร์ดแวร์
ความได้เปรียบของ GPU เหนือ CPU เพิ่มขึ้นตามขนาด batch — จาก 54.5x เมื่อประมวลผลทีละหนึ่ง combo ต่อการเรียก ไปจนถึง 359.6x ที่ 61 combo บนการ precompute indicator แบบ multi-timeframe ของเรา — เพราะ sweep ขนาดเล็กไม่สามารถ amortize ต้นทุนคงที่จากการเปิด kernel และการถ่ายโอนข้อมูลได้ เราแยกตัวเลขพาดหัว 167x ออกเป็นชัยชนะจากอัลกอริทึม 27x ที่ช่วย CPU ได้เช่นกัน และชัยชนะจากฮาร์ดแวร์ 6.2x แสดงให้เห็นว่าความได้เปรียบที่แท้จริงของ GPU เทียบกับ CPU ที่ดีที่สุดอยู่ที่เพียง 3.2x สำหรับ single-timeframe และ 6.2x สำหรับ multi พร้อมให้แนวทางตัดสินใจว่า sweep ต้องกว้างแค่ไหนก่อนที่ GPU จะคุ้มค่าที่จะซื้อมาใช้
- 10
Jun 30, 2026 #algotradingภาษี IPC: เอา Backtest Engine ไปไว้หลัง Socket แล้วเสีย 13% — แต่แทบไม่มีส่วนไหนเลยเป็นความผิดของ Socket
เรา port numba backtest kernel ตัวหนึ่งไปเป็น Rust แบบ line-for-line แล้วเรียกมันข้าม process boundary สี่วิธี พร้อม equivalence gate ที่ยืนยันว่า PnL เหมือนกันทุกประการจนถึง trade สุดท้าย การส่ง price series ทั้งชุดขนาด 1.2 MB ผ่าน Unix socket มีค่าใช้จ่ายประมาณ 2 ms — ราว 0.1% ของงานทั้งหมด การ encode payload เดียวกันด้วย JSON แพงกว่า raw bytes ถึง 1348 เท่า การเรียกแบบ chatty ทีละ combo ส่งข้อมูลซ้ำ 80 ครั้ง และ pattern การเรียกทีละ bar จะต้องจ่าย IPC ล้วนๆ 2.1 วินาทีบนงานที่ใช้เวลา 2.0 วินาที boundary นั้นถูก ภาษีอยู่ที่วิธีที่คุณข้ามมันต่างหาก