← กลับไปยังบทความ
May 26, 2026
อ่าน 5 นาที

DeepLOB: การเรียนรู้เชิงลึกบนสมุดคำสั่งซื้อขายแบบจำกัดราคา

DeepLOB: การเรียนรู้เชิงลึกบนสมุดคำสั่งซื้อขายแบบจำกัดราคา
#deep-learning
#order-book
#LOB
#microstructure
#HFT
#market-making
📖
Part 5 of 6 · Collection
Order Book & Market Microstructure

สมุดคำสั่งซื้อขายแบบจำกัดราคา (limit order book) คือโครงสร้างข้อมูลหลักของตลาดอิเล็กทรอนิกส์สมัยใหม่ ทุกคำสั่งเสนอซื้อ ทุกคำสั่งเสนอขาย ทุกการยกเลิก — ทั้งหมดอยู่ใน LOB เป็นเวลาหลายทศวรรษที่นักวิจัยเชิงปริมาณได้สร้างคุณลักษณะ (feature) จากข้อมูลนี้ด้วยมือ ไม่ว่าจะเป็นอัตราส่วนความไม่สมดุลของคำสั่ง (order imbalance ratio) ราคากลางถ่วงน้ำหนัก และสัญญาณตำแหน่งในคิว DeepLOB เลือกเส้นทางที่แตกต่างออกไป — มันเรียนรู้คุณลักษณะเหล่านี้โดยตรงจากภาพถ่ายสมุดคำสั่งดิบโดยใช้สถาปัตยกรรมแบบผสม CNN-LSTM

เผยแพร่โดย Zhang, Zohren และ Roberts ที่ Oxford-Man Institute ในปี 2019 DeepLOB แสดงให้เห็นว่าเครือข่ายเชิงลึกเดียวที่ฝึกแบบ end-to-end บนข้อมูลสมุดคำสั่งดิบนั้นสามารถแข่งขันได้หรือดีกว่า baseline แบบดั้งเดิมที่แข็งแกร่งในการทำนายการเคลื่อนไหวของราคากลาง อย่างไรก็ตาม เราควรแม่นยำเกี่ยวกับหลักฐาน ชุดข้อมูลมาตรฐาน FI-2010 เป็นชุดที่งานวิจัยส่วนใหญ่อ้างอิงถึง แต่ผู้เขียนเองกลับเรียกมันว่าไม่เพียงพอ — "สั้นเกินไป ถูกลดอัตราการสุ่มตัวอย่าง (downsampled) และนำมาจากตลาดที่มีสภาพคล่องน้อยกว่า" — และนำเสนอการประเมินผลครั้งที่สองที่ใหญ่กว่ามากบนข้อมูลของตลาดหลักทรัพย์ลอนดอน (LSE) เป็นผลลัพธ์ที่แข็งแกร่งกว่า การศึกษา LSE นั้นครอบคลุมข้อมูลหุ้นฝึกห้าตัวและหุ้นทดสอบห้าตัวประมาณหนึ่งปี มีตัวอย่างในระดับ 100 ล้านตัวอย่างขึ้นไป และแสดงให้เห็นการเรียนรู้แบบถ่ายโอน (transfer learning) นั่นคือ โมเดลที่ฝึกบนหุ้นชุดหนึ่งยังคงทำนายหุ้นที่ไม่เคยเห็นได้ ผลลัพธ์ของการถ่ายโอนนั้น ไม่ใช่ตารางคะแนน FI-2010 ต่างหากที่เป็นพาดหัวข่าวจริงของงานวิจัยนี้ บทความนี้จะวิเคราะห์สถาปัตยกรรม คณิตศาสตร์ ตัวเลขจริง และการสร้างใหม่ด้วย PyTorch ที่ใช้งานได้จริง

สมุดคำสั่งซื้อขายแบบจำกัดราคาในฐานะโครงสร้างข้อมูล

มุมมองไอโซเมตริกของสมุดคำสั่งซื้อขายแบบจำกัดราคา: ระดับปริมาณคำสั่งเสนอซื้อและเสนอขายที่เรียงซ้อนกันก่อตัวเป็นเทนเซอร์ความลึกรอบราคากลาง

สมุดคำสั่งซื้อขายแบบจำกัดราคาจะเก็บรายการสองชุดที่เรียงลำดับไว้ — คำสั่งเสนอซื้อ (bid) และคำสั่งเสนอขาย (ask) — โดยแต่ละชุดจัดเรียงตามระดับราคา ในแต่ละระดับ สมุดคำสั่งจะบันทึกราคาและปริมาณรวมของคำสั่งที่ค้างอยู่

สำหรับสมุดคำสั่งที่มี LL ระดับ ภาพถ่าย (snapshot) เดียว ณ เวลา tt คือเวกเตอร์ของค่า 4L4L ค่า:

xt=[p1a,v1a,p1b,v1b,p2a,v2a,p2b,v2b,,pLa,vLa,pLb,vLb]\mathbf{x}_t = [p_1^{a}, v_1^{a}, p_1^{b}, v_1^{b}, p_2^{a}, v_2^{a}, p_2^{b}, v_2^{b}, \ldots, p_L^{a}, v_L^{a}, p_L^{b}, v_L^{b}]

โดยที่ piap_i^{a} และ viav_i^{a} คือราคาและปริมาณเสนอขายที่ระดับ ii และ pibp_i^{b}, vibv_i^{b} คือค่าที่สอดคล้องกันในฝั่งเสนอซื้อ ระดับ 1 เก็บคำสั่งเสนอซื้อที่ดีที่สุดและคำสั่งเสนอขายที่ดีที่สุด (BBO) ส่วนต่างของทั้งสองคือสเปรด (bid-ask spread)

ในชุดข้อมูลมาตรฐาน FI-2010 ค่า L=10L = 10 ทำให้มี 40 คุณลักษณะต่อหนึ่งภาพถ่าย FI-2010 สร้างจากข้อความคำสั่งจำกัดราคาดิบประมาณ 4 ล้านข้อความจากหุ้นฟินแลนด์ห้าตัวบน NASDAQ Nordic (Kesko, Outokumpu, Sampo, Rautaruukki, Wartsila) ตลอดสิบวันทำการติดต่อกันคือวันที่ 1-14 มิถุนายน 2010 ที่สำคัญคือ DeepLOB ไม่ได้ฝึกบนภาพถ่าย 4 ล้านภาพ ชุดข้อมูลมาตรฐานนี้ลดอัตราการสุ่มตัวอย่างข้อความเหล่านั้น (ทุก 10 เหตุการณ์) ให้เป็นรูปแบบที่ทำให้เป็นมาตรฐานแล้วจำนวน 394,337 ตัวอย่าง รูปแบบที่ถูกลดอัตราการสุ่มและทำให้เป็นมาตรฐานนี้คือสิ่งที่โมเดลเห็นจริง ๆ — เป็นหนึ่งในเหตุผลที่ผู้เขียนเตือนไม่ให้ถือว่า FI-2010 เป็นคำตอบสุดท้าย

ราคากลางและการเคลื่อนไหวของมัน

ราคากลาง ณ เวลา tt คือค่าเฉลี่ยของคำสั่งเสนอซื้อและเสนอขายที่ดีที่สุด:

ptmid=p1a(t)+p1b(t)2p_t^{mid} = \frac{p_1^{a}(t) + p_1^{b}(t)}{2}

DeepLOB ทำนายทิศทางการเคลื่อนไหวของราคากลางในช่วงเวลาในอนาคต kk เหตุการณ์ ป้ายกำกับ (label) คือผลตอบแทนที่ผ่านการปรับเรียบ (smoothed return) แต่พึงระวังว่ามีแบบแผนการปรับเรียบสองแบบในวรรณกรรม และทั้งสองไม่สามารถใช้แทนกันได้:

  • ค่าเฉลี่ยอนาคตเทียบกับราคาปัจจุบัน (Tsantekidis et al.): เปรียบเทียบราคากลางเฉลี่ยในช่วง kk เหตุการณ์ถัดไปกับราคากลางปัจจุบันแบบดิบ
  • ค่าเฉลี่ยอนาคตเทียบกับค่าเฉลี่ยก่อนหน้า (Ntakaris et al. ซึ่งเป็นป้ายกำกับมาตรฐานของ FI-2010 และเป็นแบบที่ DeepLOB ใช้สำหรับข้อมูล LSE ของตน): ทั้งค่าอ้างอิงและค่าเป้าหมายต่างผ่านการปรับเรียบ
lt(k)=m+(t)m(t)m(t),m(t)=1ki=0k1ptimid,m+(t)=1ki=1kpt+imidl_t(k) = \frac{m_+(t) - m_-(t)}{m_-(t)}, \qquad m_-(t) = \frac{1}{k}\sum_{i=0}^{k-1} p_{t-i}^{mid}, \quad m_+(t) = \frac{1}{k}\sum_{i=1}^{k} p_{t+i}^{mid}

การปรับเรียบค่าอ้างอิง (ไม่ใช่แค่อนาคต) ช่วยลดสัญญาณรบกวนของป้ายกำกับจากการแกว่งตัวของราคาเพียงหนึ่งทิคได้อย่างมีนัยสำคัญ ซึ่งเป็นเหตุผลที่รูปแบบค่าเฉลี่ยก่อนหน้า/ถัดไปเป็นที่นิยมมากกว่า ไม่ว่าจะใช้แบบใด ผลตอบแทนแบบต่อเนื่องจะถูกแบ่งออกเป็นสามคลาส — ขึ้น (up), ลง (down), คงที่ (stationary) — โดยใช้เกณฑ์คงที่ ±α\pm\alpha:

yt={1if lt(k)>α0if lt(k)α1if lt(k)<αy_t = \begin{cases} 1 & \text{if } l_t(k) > \alpha \\ 0 & \text{if } |l_t(k)| \leq \alpha \\ -1 & \text{if } l_t(k) < -\alpha \end{cases}

ชุดข้อมูล FI-2010 ให้ป้ายกำกับสำหรับช่วงเวลาการทำนายห้าช่วง: k{10,20,30,50,100}k \in \{10, 20, 30, 50, 100\} เหตุการณ์

คุณลักษณะ LOB แบบดั้งเดิม

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

ความไม่สมดุลของสมุดคำสั่ง (Order Book Imbalance - OBI)

สัญญาณโครงสร้างจุลภาค (microstructure) ที่ใช้กันแพร่หลายที่สุด ที่ส่วนบนสุดของสมุดคำสั่ง:

OBI1=v1bv1av1b+v1a\text{OBI}_1 = \frac{v_1^{b} - v_1^{a}}{v_1^{b} + v_1^{a}}

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

OBIL=i=1Lvibi=1Lviai=1Lvib+i=1Lvia\text{OBI}_L = \frac{\sum_{i=1}^{L} v_i^{b} - \sum_{i=1}^{L} v_i^{a}}{\sum_{i=1}^{L} v_i^{b} + \sum_{i=1}^{L} v_i^{a}}

ราคากลางถ่วงน้ำหนักด้วยปริมาณ

ราคากลางมาตรฐานถ่วงน้ำหนักทั้งสองฝั่งเท่ากัน ราคากลางถ่วงน้ำหนักด้วยปริมาณ (เรียกอีกอย่างว่า weighted mid หรือ VAMP) เอนเอียงไปทางฝั่งที่หนักกว่าของสมุดคำสั่ง เมื่อเขียนความไม่สมดุลที่ส่วนบนสุดเป็น I=v1b/(v1b+v1a)I = v_1^{b}/(v_1^{b}+v_1^{a}) มันคือค่าเฉลี่ยถ่วงน้ำหนักด้วยความไม่สมดุลของราคาทั้งสอง:

pwmid=Ip1a+(1I)p1b=v1bp1a+v1ap1bv1b+v1ap^{wmid} = I\, p_1^{a} + (1 - I)\, p_1^{b} = \frac{v_1^{b}\, p_1^{a} + v_1^{a}\, p_1^{b}}{v_1^{b} + v_1^{a}}

สังเกตการถ่วงน้ำหนักไขว้: ราคาเสนอขายถูกถ่วงน้ำหนักด้วยปริมาณเสนอซื้อ และในทางกลับกัน เมื่อปริมาณเสนอซื้อมีอิทธิพลเหนือกว่า (I1I \to 1) ราคากลางถ่วงน้ำหนักจะเลื่อนไปทางฝั่งเสนอขาย — สะท้อนความคาดหวังว่าสมุดคำสั่งที่ไม่สมดุลจะคลี่คลายโดยการเคลื่อนไปทางฝั่งที่หนักกว่า

ขอเตือนเรื่องการตั้งชื่อ ราคากลางถ่วงน้ำหนักด้วยปริมาณแบบสถิตนี้ ไม่ใช่ microprice ของ Stoikov micro-price ของ Stoikov (2018) เป็นตัวประมาณค่าที่ปรับด้วยมาร์ติงเกล (martingale-adjusted estimator) Mt+g(I,S)M_t + g(I, S) ซึ่งได้มาจากการแก้ไขแบบเรียกซ้ำสำหรับวิธีที่สเปรดและความไม่สมดุลพัฒนาไป — ประเด็นหลักของเขาคือราคากลางถ่วงน้ำหนักแบบไร้เดียงสานั้นมีอคติและไม่ใช่มาร์ติงเกล ทั้งสองเป็นวัตถุที่แตกต่างกันสองชนิด เราใช้ราคากลางถ่วงน้ำหนักในที่นี้เพราะความเรียบง่ายของมัน ไม่ใช่ในฐานะตัวแทนของ microprice

ความไม่สมดุลของความลึก (Depth Imbalance)

วัดรูปร่างของสมุดคำสั่งที่ลึกเกินกว่า BBO:

DIi=vibviavib+via,i=1,,L\text{DI}_i = \frac{v_i^{b} - v_i^{a}}{v_i^{b} + v_i^{a}}, \quad i = 1, \ldots, L

สเปรดและสเปรดสัมพัทธ์

st=p1a(t)p1b(t),strel=stptmids_t = p_1^{a}(t) - p_1^{b}(t), \qquad s_t^{rel} = \frac{s_t}{p_t^{mid}}

คุณลักษณะเหล่านี้ทรงพลังแต่ก็มีข้อจำกัด พวกมันต้องอาศัยความเชี่ยวชาญเฉพาะด้านในการออกแบบ ไม่สามารถจับปฏิสัมพันธ์แบบไม่เชิงเส้นที่ซับซ้อนได้ และละเลยพลวัตเชิงเวลาตลอดภาพถ่ายที่ต่อเนื่องกัน DeepLOB จัดการกับข้อจำกัดทั้งสามข้อนี้

สถาปัตยกรรมของ DeepLOB

สถาปัตยกรรมของ DeepLOB: เทนเซอร์สมุดคำสั่งดิบไหลผ่านเลเยอร์คอนโวลูชัน โมดูล inception และ LSTM

สถาปัตยกรรมประกอบด้วยสามบล็อก แต่ละบล็อกมีบทบาทเฉพาะตัว:

  1. บล็อกคอนโวลูชัน (Convolutional block) — สกัดคุณลักษณะเชิงพื้นที่จากภาพถ่ายสมุดคำสั่ง
  2. โมดูล inception — จับรูปแบบเชิงเวลาแบบหลายสเกล
  3. บล็อก LSTM — สร้างแบบจำลองการพึ่งพาเชิงลำดับตลอดเวลา

อินพุตของเครือข่ายคือเทนเซอร์ที่มีรูปร่าง (T,L×4)(T, L \times 4) โดยที่ TT คือหน้าต่างมองย้อนหลัง (lookback window) (100 ขั้นเวลาในงานวิจัย) และ L×4=40L \times 4 = 40 สำหรับ 10 ระดับของราคาและปริมาณทั้งสองฝั่ง

บล็อก 1: การสกัดคุณลักษณะแบบคอนโวลูชัน

เลเยอร์คอนโวลูชันแรกทำงานตามมิติคุณลักษณะเพื่อเรียนรู้ปฏิสัมพันธ์ระหว่างราคาและปริมาณในแต่ละระดับ

เลเยอร์ 1: คอนโวลูชันที่มีขนาดฟิลเตอร์ 1×21 \times 2 และสไตรด์ (1,2)(1, 2) ที่ใช้กับแต่ละคู่ราคา-ปริมาณ สิ่งนี้สรุปแต่ละคู่ (pi,vi)(p_i, v_i) ให้เป็นคุณลักษณะเดียว — คล้ายกับการคำนวณ "ปฏิสัมพันธ์ราคา-ปริมาณ" ในแต่ละระดับ ความกว้างหดจาก 40 เหลือ 20

เลเยอร์ 2: คอนโวลูชัน 1×21 \times 2 สไตรด์ (1,2)(1, 2) ที่ทำงานข้ามคู่เสนอซื้อ-เสนอขายที่จับคู่กันในระดับเดียวกัน สิ่งนี้จับข้อมูลสเปรดและความไม่สมดุลในแต่ละระดับ ความกว้างหดจาก 20 เหลือ 10

เลเยอร์ 3: คอนโวลูชัน 1×101 \times 10 ที่รวมข้ามทั้ง 10 ระดับ ยุบมิติความลึกให้เหลือความกว้าง 1 สิ่งนี้สร้างคุณลักษณะรวมเดียวต่อขั้นเวลาที่เข้ารหัสโปรไฟล์ความลึกทั้งหมด

แต่ละขั้น 1×21 \times 2 / 1×101 \times 10 ตามด้วยคอนโวลูชัน (4,1)(4, 1) สองตัวตามแกนเวลา แต่ละตัวมีฟังก์ชันกระตุ้น LeakyReLU และ batch normalization โปรดสังเกตว่าคอนโวลูชัน (4,1)(4, 1) เหล่านี้ที่มี padding=(1, 0) ไม่ได้ รักษามิติเวลาไว้: แต่ละตัวจะทำให้มันสั้นลงหนึ่งขั้น (Tout=Tin1T_{\text{out}} = T_{\text{in}} - 1) ตลอดหกเลเยอร์ดังกล่าวในบล็อก 1-3 แกนเวลาหดจาก 100 เหลือ 94 ก่อนถึงโมดูล inception — สิ่งที่คอมเมนต์เกี่ยวกับรูปร่างในโค้ดด้านล่างทำให้ชัดเจน

การออกแบบหลีกเลี่ยงฟิลเตอร์เชิงพื้นที่ขนาดใหญ่โดยเจตนา ฟิลเตอร์ 1×21 \times 2 เคารพโครงสร้างการจับคู่ตามธรรมชาติของข้อมูล LOB — ราคากับปริมาณ เสนอซื้อกับเสนอขาย อคติเชิงอุปนัย (inductive bias) นี้สำคัญยิ่ง: ฟิลเตอร์ 3×33 \times 3 จะผสมระดับและฝั่งที่อยู่ติดกันในแบบที่ไม่มีความหมายทางการเงิน

บล็อก 2: โมดูล Inception

หลังจากบล็อกคอนโวลูชันลด 40 คุณลักษณะให้เป็นการแทนเชิงพื้นที่ที่กระชับ (ความกว้าง 1) โมดูล inception จะทำงานตามมิติเวลาเพื่อจับรูปแบบที่หลายสเกลเวลาพร้อมกัน

โมดูล inception ของ DeepLOB มีเส้นทางขนาน สี่ เส้นทาง แต่ละเส้นทางสร้าง 32 ช่อง (channel) ซึ่งทั้งหมดถูกต่อเชื่อม (concatenate) เข้าด้วยกัน:

  • คอขวด 1×11 \times 1 \to คอนโวลูชันเชิงเวลา 3×13 \times 1: รูปแบบเชิงเวลาระยะสั้น (3 ขั้นเวลา)
  • คอขวด 1×11 \times 1 \to คอนโวลูชันเชิงเวลา 5×15 \times 1: รูปแบบเชิงเวลาระยะกลาง (5 ขั้นเวลา)
  • max-pool 3×13 \times 1 \to คอนโวลูชัน 1×11 \times 1: เส้นทาง pooling ที่รักษามุมมองที่ผ่านการปรับเรียบและลดอัตราการสุ่มไว้
  • (การลดขนาด 1×11 \times 1 ทำหน้าที่เป็นคอขวด ณ จุดเวลาก่อนคอนโวลูชันเชิงเวลา)

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

สิ่งนี้ได้รับแรงบันดาลใจจากสถาปัตยกรรม inception ของ GoogLeNet แต่ปรับให้เข้ากับข้อมูลเชิงเวลาแบบ 1 มิติแทนที่จะเป็นภาพ 2 มิติ ข้อมูลเชิงลึกที่สำคัญคือ พลวัตของ LOB ดำเนินไปที่หลายสเกลเวลา: สัญญาณรบกวนแบบทิคต่อทิค โมเมนตัมระยะสั้น และการกลับสู่ค่าเฉลี่ย (mean reversion) ในช่วงเวลาที่ยาวกว่า ล้วนอยู่ร่วมกัน

การสร้างใหม่ด้วย PyTorch ด้านล่างนำเสนอ รูปแบบสามเส้นทางที่ทำให้เรียบง่ายขึ้น (คอนโวลูชันเชิงเวลาสองตัวบวกกับเส้นทาง 1×11\times1) เพื่อให้โค้ดอ่านง่าย ซึ่งละเว้นเส้นทาง max-pool เราชี้ให้เห็นสิ่งนี้อย่างชัดเจนเพราะมันเป็นการเบี่ยงเบนจากงานวิจัย ไม่ใช่โมดูลต้นฉบับ

บล็อก 3: การสร้างแบบจำลองลำดับด้วย LSTM

เอาต์พุตของโมดูล inception ถูกป้อนเข้าสู่เลเยอร์ LSTM ที่ประมวลผลลำดับความยาว TT ทั้งหมด LSTM จับการพึ่งพาเชิงเวลาระยะไกลที่คอนโวลูชันเพียงอย่างเดียวจะพลาดไป — การเปลี่ยนแปลงระบอบ (regime change) ผลกระทบของช่วงเวลาในวัน และสภาวะตลาดที่เปลี่ยนแปลง

สถานะซ่อน (hidden state) สุดท้ายของ LSTM ถูกส่งผ่านเลเยอร์เชื่อมต่อเต็มที่ (fully connected) ที่มีฟังก์ชันกระตุ้น softmax เพื่อสร้างการแจกแจงความน่าจะเป็นเหนือสามคลาส (ขึ้น ลง คงที่)

ฟังก์ชันการสูญเสีย (Loss Function)

โมเดลถูกฝึกด้วย categorical cross-entropy:

L=1Ni=1Nc=13yi,clog(y^i,c)\mathcal{L} = -\frac{1}{N} \sum_{i=1}^{N} \sum_{c=1}^{3} y_{i,c} \log(\hat{y}_{i,c})

โดยที่ yi,cy_{i,c} คือป้ายกำกับจริงที่เข้ารหัสแบบ one-hot และ y^i,c\hat{y}_{i,c} คือความน่าจะเป็นที่ทำนายสำหรับคลาส cc

การสร้างใหม่ด้วย PyTorch

DeepLOB ต้นฉบับสร้างขึ้นใน Keras บนแบ็กเอนด์ TensorFlow ภายหลังคลังโค้ดของผู้เขียน (zcakhaa) ได้เพิ่มเวอร์ชันพอร์ตเป็น PyTorch โค้ดด้านล่างเป็นการสร้างใหม่ด้วย PyTorch เพื่อเป็นตัวอย่างของเราเอง ไม่ใช่ฉบับทางการ มันเบี่ยงเบนจากงานวิจัยในสองด้านที่เราระบุไว้แบบ inline: มันละเว้นเส้นทาง max-pool ของ inception (สามเส้นทางแทนที่จะเป็นสี่) และมันขยายจำนวนช่องขึ้น งานวิจัยใช้ 16 ฟิลเตอร์ ตลอดบล็อกคอนโวลูชันและ 32 ฟิลเตอร์ต่อเส้นทาง inception (อินพุตของ LSTM คือ 3×32=963 \times 32 = 96) ทำให้ได้โมเดลที่กระชับราว 60,000 พารามิเตอร์ ตัวอย่างโค้ดด้านล่างใช้คอนโวลูชัน 32 / ฟิลเตอร์ inception 64 (อินพุต LSTM 192) — สอดคล้องกันภายในและรันได้ แต่หนักกว่าต้นฉบับ เพื่อให้ตรงกับงานวิจัย ให้ตั้งค่าช่องคอนโวลูชันเป็น 16, ช่อง inception เป็น 32 และ input_size=96

import torch
import torch.nn as nn


class DeepLOB(nn.Module):
    """
    DeepLOB-style CNN-Inception-LSTM for limit order books.
    Reimplementation inspired by Zhang, Zohren, Roberts (2019),
    IEEE Transactions on Signal Processing, arXiv:1808.03668.

    NOTE: this is an illustrative reimplementation, NOT the official model.
    Differences from the paper:
      - inception has 3 paths here vs 4 in the paper (max-pool path omitted);
      - channel counts are scaled up (paper: 16 conv / 32 inception, input 96).

    Input shape: (batch_size, 1, T, 40)
        T = lookback window (e.g. 100)
        40 = 10 levels x 4 features (ask_price, ask_vol, bid_price, bid_vol)
    """

    def __init__(self, num_classes: int = 3, T: int = 100):
        super().__init__()
        self.num_classes = num_classes

        self.conv1 = nn.Sequential(
            nn.Conv2d(1, 32, kernel_size=(1, 2), stride=(1, 2)),
            nn.LeakyReLU(negative_slope=0.01),
            nn.BatchNorm2d(32),
            nn.Conv2d(32, 32, kernel_size=(4, 1), padding=(1, 0)),  # time -1
            nn.LeakyReLU(negative_slope=0.01),
            nn.BatchNorm2d(32),
            nn.Conv2d(32, 32, kernel_size=(4, 1), padding=(1, 0)),  # time -1
            nn.LeakyReLU(negative_slope=0.01),
            nn.BatchNorm2d(32),
        )

        self.conv2 = nn.Sequential(
            nn.Conv2d(32, 32, kernel_size=(1, 2), stride=(1, 2)),
            nn.LeakyReLU(negative_slope=0.01),
            nn.BatchNorm2d(32),
            nn.Conv2d(32, 32, kernel_size=(4, 1), padding=(1, 0)),  # time -1
            nn.LeakyReLU(negative_slope=0.01),
            nn.BatchNorm2d(32),
            nn.Conv2d(32, 32, kernel_size=(4, 1), padding=(1, 0)),  # time -1
            nn.LeakyReLU(negative_slope=0.01),
            nn.BatchNorm2d(32),
        )

        self.conv3 = nn.Sequential(
            nn.Conv2d(32, 32, kernel_size=(1, 10)),
            nn.LeakyReLU(negative_slope=0.01),
            nn.BatchNorm2d(32),
            nn.Conv2d(32, 32, kernel_size=(4, 1), padding=(1, 0)),  # time -1
            nn.LeakyReLU(negative_slope=0.01),
            nn.BatchNorm2d(32),
            nn.Conv2d(32, 32, kernel_size=(4, 1), padding=(1, 0)),  # time -1
            nn.LeakyReLU(negative_slope=0.01),
            nn.BatchNorm2d(32),
        )

        self.inp1 = nn.Sequential(
            nn.Conv2d(32, 64, kernel_size=(1, 1), padding=(0, 0)),
            nn.LeakyReLU(negative_slope=0.01),
            nn.BatchNorm2d(64),
        )
        self.inp2 = nn.Sequential(
            nn.Conv2d(32, 64, kernel_size=(1, 1), padding=(0, 0)),
            nn.LeakyReLU(negative_slope=0.01),
            nn.BatchNorm2d(64),
            nn.Conv2d(64, 64, kernel_size=(3, 1), padding=(1, 0)),
            nn.LeakyReLU(negative_slope=0.01),
            nn.BatchNorm2d(64),
        )
        self.inp3 = nn.Sequential(
            nn.Conv2d(32, 64, kernel_size=(1, 1), padding=(0, 0)),
            nn.LeakyReLU(negative_slope=0.01),
            nn.BatchNorm2d(64),
            nn.Conv2d(64, 64, kernel_size=(5, 1), padding=(2, 0)),
            nn.LeakyReLU(negative_slope=0.01),
            nn.BatchNorm2d(64),
        )

        self.lstm = nn.LSTM(
            input_size=192,  # 64 * 3 paths from the simplified inception
            hidden_size=64,
            num_layers=1,
            batch_first=True,
        )

        self.fc = nn.Linear(64, num_classes)

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        """
        Args:
            x: Tensor of shape (batch, 1, T, 40)
        Returns:
            Tensor of shape (batch, num_classes)
        """
        h = self.conv1(x)   # (batch, 32, T-2, 20)
        h = self.conv2(h)   # (batch, 32, T-4, 10)
        h = self.conv3(h)   # (batch, 32, T-6, 1)   e.g. T=100 -> 94

        h_inp1 = self.inp1(h)  # (batch, 64, T-6, 1)
        h_inp2 = self.inp2(h)  # (batch, 64, T-6, 1)
        h_inp3 = self.inp3(h)  # (batch, 64, T-6, 1)
        h = torch.cat([h_inp1, h_inp2, h_inp3], dim=1)  # (batch, 192, T-6, 1)

        h = h.squeeze(-1)          # (batch, 192, T-6)
        h = h.permute(0, 2, 1)     # (batch, T-6, 192)

        h, _ = self.lstm(h)
        h = h[:, -1, :]  # take last hidden state

        out = self.fc(h)
        return out

การประมวลผลข้อมูลก่อน (Data Preprocessing)

ชุดข้อมูล FI-2010 มาพร้อมการทำให้เป็นมาตรฐานแบบ z-score สำหรับข้อมูลสมุดคำสั่งแบบสด คุณต้องทำให้เป็นมาตรฐานในลักษณะเดียวกัน:

import numpy as np
from torch.utils.data import Dataset


class LOBDataset(Dataset):
    """Dataset for limit order book snapshots."""

    def __init__(
        self,
        data: np.ndarray,
        labels: np.ndarray,
        T: int = 100,
    ):
        """
        Args:
            data: shape (num_snapshots, 40), raw LOB features
            labels: shape (num_snapshots,), class labels {0, 1, 2}
            T: lookback window length
        """
        self.data = data
        self.labels = labels
        self.T = T

        self.mean = data[:len(data) // 2].mean(axis=0)
        self.std = data[:len(data) // 2].std(axis=0)
        self.std[self.std == 0] = 1.0
        self.data = (self.data - self.mean) / self.std

    def __len__(self) -> int:
        return len(self.data) - self.T

    def __getitem__(self, idx: int):
        x = self.data[idx : idx + self.T].reshape(1, self.T, 40)
        y = self.labels[idx + self.T - 1]
        return torch.tensor(x, dtype=torch.float32), torch.tensor(
            y, dtype=torch.long
        )

ลูปการฝึก (Training Loop)

def train_deeplob(
    model: DeepLOB,
    train_loader,
    val_loader,
    epochs: int = 50,
    lr: float = 0.01,
    device: str = "cuda",
):
    model = model.to(device)
    criterion = nn.CrossEntropyLoss()
    optimizer = torch.optim.Adam(model.parameters(), lr=lr, eps=1)

    best_val_f1 = 0.0
    for epoch in range(epochs):
        model.train()
        train_loss = 0.0
        for x_batch, y_batch in train_loader:
            x_batch = x_batch.to(device)
            y_batch = y_batch.to(device)

            optimizer.zero_grad()
            logits = model(x_batch)
            loss = criterion(logits, y_batch)
            loss.backward()
            optimizer.step()
            train_loss += loss.item()

        model.eval()
        all_preds, all_labels = [], []
        with torch.no_grad():
            for x_val, y_val in val_loader:
                x_val = x_val.to(device)
                preds = model(x_val).argmax(dim=1).cpu()
                all_preds.extend(preds.numpy())
                all_labels.extend(y_val.numpy())

        from sklearn.metrics import f1_score
        val_f1 = f1_score(all_labels, all_preds, average="weighted")

        print(
            f"Epoch {epoch+1}/{epochs} | "
            f"Train Loss: {train_loss/len(train_loader):.4f} | "
            f"Val F1: {val_f1:.4f}"
        )

        if val_f1 > best_val_f1:
            best_val_f1 = val_f1
            torch.save(model.state_dict(), "deeplob_best.pt")

ไฮเปอร์พารามิเตอร์การฝึกที่สำคัญจากงานวิจัยต้นฉบับ:

  • Optimizer: Adam ที่มี ϵ=1\epsilon = 1 (ใหญ่ผิดปกติ — ช่วยทำให้การอัปเดตมีเสถียรภาพบนข้อมูลทางการเงินที่มีสัญญาณรบกวน)
  • อัตราการเรียนรู้ (Learning rate): 0.01
  • ขนาด batch: 32
  • หน้าต่างมองย้อนหลัง: T=100T = 100 ขั้นเวลา

เราติดตามค่า weighted F1 มากกว่าความแม่นยำ (accuracy) ในการตรวจสอบ เพราะสามคลาสนั้นไม่สมดุล — และดังที่หัวข้อถัดไปแสดง F1 คือเมตริกที่งานวิจัยต้นฉบับเน้นย้ำด้วยเหตุผลนั้นพอดี

DeepLOB ถูกสร้างขึ้นเพื่อจับอะไร

สัญญาณโครงสร้างจุลภาคที่ DeepLOB เรียนรู้: ความไม่สมดุลของกระแสคำสั่ง พลวัตของคิว และแรงกดดันของราคากลางถ่วงน้ำหนักด้วยปริมาณ

แง่มุมที่น่าสนใจอย่างหนึ่งของ DeepLOB คือบล็อกของมัน ได้รับแรงบันดาลใจจาก คุณลักษณะที่สร้างด้วยมือข้างต้นอย่างใกล้ชิดเพียงใด เราต้องการระมัดระวังตรงนี้: งานวิจัยนำเสนอสิ่งเหล่านี้ในฐานะสัญชาตญาณการออกแบบ ไม่ใช่ในฐานะคุณสมบัติที่พิสูจน์แล้วของเครือข่ายที่ฝึกแล้ว มันไม่ได้เผยแพร่การแสดงภาพฟิลเตอร์ (filter visualization) ความสัมพันธ์ของการกระตุ้น-ความไม่สมดุล หรือการวิเคราะห์ว่า LSTM ให้ความสนใจกับสิ่งใด ดังนั้นโปรดอ่านสิ่งต่อไปนี้ในฐานะเจตนาเชิงสถาปัตยกรรม ไม่ใช่ผลการวัด

บล็อกคอนโวลูชันแรก ฟิลเตอร์ 1×21 \times 2 จับคู่ราคากับปริมาณในแต่ละระดับ ในเชิงโครงสร้าง นี่คือการดำเนินการเดียวกับที่ก่อตัวเป็นราคาถ่วงน้ำหนักด้วยปริมาณ — งานวิจัยอธิบายแรงจูงใจของเลเยอร์แรกโดยชี้ว่าแผนที่คุณลักษณะ (feature map) ของมันก่อตัวเป็นปริมาณที่คล้าย micro-price เครือข่าย ถูกสร้างขึ้นเพื่อ กู้คืนบางสิ่งในตระกูลนั้น เราไม่ได้อ้างว่ามันค้นพบตัวประมาณค่าใดโดยเฉพาะขึ้นมาใหม่ได้อย่างพิสูจน์ได้

บล็อกคอนโวลูชันที่สอง โดยการทำงานข้ามคู่เสนอซื้อ-เสนอขาย ฟิลเตอร์เหล่านี้อยู่ในตำแหน่งที่จะเรียนรู้คุณลักษณะที่คล้ายความไม่สมดุลในหลายระดับ — อีกครั้ง โดยการก่อสร้างมากกว่าโดยความสัมพันธ์ที่แสดงให้เห็นแล้ว

โมดูล inception คอนโวลูชันเชิงเวลาแบบหลายสเกลมีจุดมุ่งหมายเพื่อจับโมเมนตัมที่ความถี่ต่างกัน: เส้นทาง 1×11\times1 ตอบสนองต่อโครงสร้าง ณ จุดเวลา เส้นทาง 3×13\times1 ต่อแนวโน้มระยะสั้น เส้นทาง 5×15\times1 ต่อแนวโน้มที่ยาวกว่าเล็กน้อย และ (ในโมดูลเต็ม) เส้นทาง max-pool ต่อมุมมองที่ผ่านการปรับเรียบ

เลเยอร์ LSTM ส่วนประกอบแบบเรียกซ้ำ (recurrent) เพิ่มความจำของการพึ่งพาระยะไกลที่คอนโวลูชันไม่สามารถแทนได้ — การเปลี่ยนแปลงระบอบและผลกระทบของช่วงเวลาในวัน เราหลีกเลี่ยงการอ้างที่หนักแน่นกว่านี้ (เช่นว่า LSTM นำ "ความสนใจแบบปรับตัว (adaptive attention)" มาใช้ที่ถ่วงน้ำหนักข้อมูลล่าสุดใหม่ในระบอบที่ผันผวน) เพราะงานวิจัยไม่ได้แสดงสิ่งนี้

ประสิทธิภาพบน FI-2010

งานวิจัยต้นฉบับประเมินสองโปรโตคอล Setup 1 ใช้การแบ่งการทำให้เป็นมาตรฐานช่วงต้นของชุดข้อมูล Setup 2 คือชุดการเรียนรู้เชิงลึกที่งานในภายหลังส่วนใหญ่นำมาเปรียบเทียบ เนื่องจาก FI-2010 มีคลาสที่ไม่สมดุล งานวิจัยจึงเน้น F1 ไม่ใช่ความแม่นยำ และรายงานตัวเลขที่อิงกับ precision/recall สำหรับ baseline ที่ไม่ใช่นิวรัล (SVM, MLP) ต่อไปนี้คือตัวเลข Setup 2 จริง (F1, %):

ช่วงเวลา (k) SVM MLP CNN-I LSTM DeepLOB
10 35.88 48.27 55.21 66.33 83.40
20 72.82
50 80.35

ที่ k=10k = 10 DeepLOB ยังรายงานความแม่นยำ 84.47% ควบคู่กับ F1 ที่ 83.40 ของมัน Setup 2 รายงานเฉพาะ k{10,20,50}k \in \{10, 20, 50\} — ไม่มีแถว k=100k = 100 ที่นี่ (Setup 1 รายงาน k{10,50,100}k \in \{10, 50, 100\} โดย DeepLOB มี F1 ที่ 77.66 / 74.96 / 76.58 ตามลำดับ) เครื่องหมายขีด (—) ข้างต้นบ่งบอกช่อง baseline ที่งานวิจัยไม่ได้จัดทำตารางในช่วงเวลาเหล่านั้นในโปรโตคอลนี้

มีข้อสังเกตหลายประการที่โดดเด่น:

  1. DeepLOB เอาชนะ baseline ด้วยส่วนต่างที่กว้างในช่วงเวลาสั้น ที่ k=10k = 10 F1 ของมัน (83.40) สูงกว่า LSTM (66.33), CNN-I (55.21), MLP (48.27) และ SVM (35.88) อย่างมาก การจัดอันดับเชิงคุณภาพ — โมเดลแบบ recurrent-convolutional เชิงลึกเหนือกว่า CNN ธรรมดา MLP และ SVM — คือบทสรุปที่แข็งแกร่ง
  2. แนวโน้มของช่วงเวลาไม่เป็นแบบเอกภาพ ไม่ใช่ "ยาวกว่าง่ายกว่า" ทั่ว Setup 2 F1 ของ DeepLOB เปลี่ยนเป็น 83.4072.8280.3583.40 \to 72.82 \to 80.35 เมื่อ kk เปลี่ยนเป็น 10205010 \to 20 \to 50 — รูปแบบรูปตัว U โดย k=20k=20 ยากที่สุด ไม่ใช่การไต่ขึ้นที่สะอาด ว่าช่วงเวลาใด "ง่ายกว่า" ขึ้นอยู่อย่างมากกับ setup เกณฑ์ α\alpha และแบบแผนการปรับเรียบป้ายกำกับ เราไม่ควรอ่านกฎสากลจากตัวเลขเหล่านี้
  3. DeepLOB ไม่ได้เหนือกว่าทุกวิธีแบบดั้งเดิมในทุกช่อง เมื่อเทียบกับ baseline ที่แข็งแกร่งเช่น C(TABL) ส่วนต่างจะแคบลงในบางช่วงเวลา ดังนั้น "เหนือกว่าทุกแนวทางแบบดั้งเดิมทุกที่" จึงเป็นการกล่าวเกินจริง การอ้างที่ปกป้องได้คือมันแข่งขันได้ถึงดีที่สุด และดีที่สุดอย่างชัดเจนในช่วงเวลาสั้น

และอีกครั้ง: มุมมองของงานวิจัยเองคือ FI-2010 เล็กเกินไปและถูกลดอัตราการสุ่มมากเกินไปที่จะตัดสินคำถามนี้ หลักฐานที่แข็งแกร่งกว่าของมันคือการศึกษา LSE ที่ DeepLOB ฝึกบนหุ้นชุดหนึ่งและยังคงทำนายหุ้นที่กันไว้ (held-out stocks) — ผลลัพธ์การเรียนรู้แบบถ่ายโอนที่ FI-2010 ไม่สามารถแสดงได้

LOBFrame และวิกฤตการทำซ้ำ (Replication Crisis)

เส้นโค้งในกลุ่มตัวอย่าง (in-sample) และนอกกลุ่มตัวอย่าง (out-of-sample) ที่แตกต่างกัน แสดงให้เห็นวิกฤตการทำซ้ำของการเรียนรู้เชิงลึกบนสมุดคำสั่ง

กรอบงานมาตรฐาน LOBFrame (Briola, Bartolucci, Aste, 2024) เป็นส่วนเสริมที่ทำให้เราตื่นตัวต่อผลลัพธ์เหล่านี้ แม้สถาปัตยกรรมของ DeepLOB จะมีความมั่นคง แต่กรอบงานนี้เน้นข้อควรระวังสำคัญหลายประการ:

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

การทำนาย vs. กำไร ความแม่นยำในการจำแนกประเภทที่สูงไม่ได้แปลเป็นกำไรจากการเทรดโดยอัตโนมัติ LOBFrame เน้นเมตริกที่ผูกกับว่าการเคลื่อนไหวที่ทำนายนั้นใหญ่พอที่จะข้ามสเปรดหรือไม่ โมเดลต้องถูกต้องบ่อยพอ และบนการเคลื่อนไหวที่ใหญ่พอ เพื่อเอาชนะสเปรด — และสำหรับหุ้นที่สเปรดแคบ เกณฑ์นั้นสูง

ความไวต่อป้ายกำกับ การเลือกเกณฑ์ α\alpha และช่วงเวลา kk ส่งผลอย่างมากต่อทั้งความแม่นยำที่รายงานและคุณค่าในทางปฏิบัติของการทำนาย ป้ายกำกับที่แคบเกินไปสร้างเป้าหมายที่มีสัญญาณรบกวน ป้ายกำกับที่กว้างเกินไปสร้างการทำนายที่ "แม่นยำ" อย่างไม่มีความหมายแต่ไร้ประโยชน์

เหนือกว่า DeepLOB: ภูมิทัศน์ปัจจุบัน

กลุ่มดาวของแนวทางการพยากรณ์สมุดคำสั่งสมัยใหม่ที่โคจรรอบโมเดล DeepLOB ดั้งเดิม

ตั้งแต่การเผยแพร่ DeepLOB มีส่วนขยายหลายอย่างปรากฏขึ้น:

Transformers สำหรับสมุดคำสั่งซื้อขายแบบจำกัดราคา (Wallbridge, 2020) มักถูกอ้างถึงอย่างหลวม ๆ ว่า "TransLOB" ในวรรณกรรมภายหลัง ตัวโมเดลเองเป็นตัวสกัดคุณลักษณะแบบ causal/dilated convolutional ตามด้วย masked multi-head self-attention — ไม่ใช่แค่ DeepLOB ที่สลับ LSTM เป็น Transformer มันไม่ได้นำสแต็ก inception+conv กลับมาใช้ใหม่ มันรายงาน state of the art ใหม่ของ FI-2010 สำหรับยุคนั้น

ตัวแปรในโดเมนคริปโต หลายกลุ่มนำสถาปัตยกรรมแบบ DeepLOB ไปใช้กับตลาดสกุลเงินดิจิทัล ที่ซึ่งพลวัตของสมุดคำสั่งแตกต่างจากหุ้นอย่างมาก — สเปรดที่กว้างกว่า การเทรดตลอด 24/7 และส่วนผสมของผู้เข้าร่วมที่ต่างกัน ซึ่งทั้งหมดต้องการการฝึกใหม่

ตัวแปรที่เสริมด้วย attention มีแนวงานวิจัยที่แทรก multi-head attention ระหว่างบล็อก inception และ LSTM ให้เครือข่ายโฟกัสไปที่ระดับหรือขั้นเวลาที่ให้ข้อมูลมากที่สุดสำหรับการทำนายปัจจุบัน

LOB-Bench (Nagy, Frey, Li, Sarkar, Vyetrenko, Zohren, Calinescu, Foerster, 2025) กรอบงานมาตรฐานนี้เปลี่ยนความสนใจจากการทำนายไปสู่การ สร้าง (generation) โดยให้คะแนนว่าโมเดลสร้าง (generative model) ของข้อมูลสมุดคำสั่งนั้นสมจริงเพียงใด — เกี่ยวข้องกับการทำ backtest และการฝึก agent มากกว่าการพยากรณ์ทิศทาง

ข้อพิจารณาเชิงปฏิบัติสำหรับการใช้งานจริง

หากคุณกำลังพิจารณาการนำโมเดลแบบ DeepLOB ไปใช้ในระบบเทรดสด จะมีข้อกังวลทางวิศวกรรมหลายประการเกิดขึ้น:

ความหน่วง (Latency)

โมเดลต้องสร้างการทำนายภายในงบประมาณความหน่วงของระบบเทรดของคุณ สำหรับระบบ HFT ที่ทำงานที่ความหน่วงระดับต่ำกว่ามิลลิวินาที แม้แต่การอนุมาน PyTorch ที่ปรับให้เหมาะสมแล้วก็อาจช้าเกินไป ทางเลือกได้แก่:

  • การส่งออก ONNX พร้อมการปรับให้เหมาะสมด้วย TensorRT
  • การทำ Quantization เป็น INT8
  • การใช้งานบน FPGA สำหรับแอปพลิเคชันที่ไวต่อความหน่วงมากที่สุด

ไปป์ไลน์ข้อมูล (Data Pipeline)

โมเดลคาดหวังภาพถ่ายสมุดคำสั่งที่ทำให้เป็นมาตรฐานและจัดเรียงแล้วที่ความถี่คงที่ ในทางปฏิบัติ การอัปเดต LOB มาถึงแบบไม่ประสานเวลา (asynchronously) คุณต้องมี:

  • เครื่องยนต์สร้างภาพถ่ายใหม่ที่รักษาสถานะสมุดคำสั่งปัจจุบัน
  • ตัวสุ่มตัวอย่างความถี่คงที่ที่สร้างเทนเซอร์อินพุต (T,40)(T, 40)
  • การทำให้เป็นมาตรฐานแบบออนไลน์โดยใช้สถิติแบบเลื่อน (rolling statistics)

เสถียรภาพของคุณลักษณะ (Feature Stability)

พารามิเตอร์การทำให้เป็นมาตรฐานแบบ z-score ที่คำนวณบนข้อมูลฝึกจะเลื่อน (drift) ไปตามเวลา ราคาเปลี่ยน ระบอบความผันผวนเลื่อน โครงสร้างตลาดวิวัฒนาการ ระบบที่ใช้งานจริงต้องการ:

  • หน้าต่างการทำให้เป็นมาตรฐานแบบเลื่อน (เช่น คำนวณสถิติใหม่ทุกวัน)
  • การตรวจจับระบอบเพื่อกระตุ้นการฝึกโมเดลใหม่
  • การติดตามการเลื่อนของการแจกแจงอินพุต

การ Overfit กับโครงสร้างจุลภาค

รูปแบบ LOB เป็นแบบเฉพาะตลาดและเฉพาะตราสาร โมเดลที่ฝึกบนหุ้น NASDAQ จะไม่ทำงานบน Binance BTC/USDT โดยไม่มีการฝึกใหม่ แม้แต่ภายในตลาดเดียวกัน โมเดลก็สามารถ overfit กับ:

  • ระบอบขนาดทิค (หุ้นทิคใหญ่ vs. ทิคเล็ก)
  • รูปแบบช่วงเวลาในวัน (การประมูลเปิด ช่วงซบเซากลางวัน การปิดแบบไขว้)
  • พฤติกรรมของผู้ดูแลสภาพคล่อง (market maker) ที่เปลี่ยนไปตามเวลา

บทสรุป

DeepLOB เป็นตัวแทนของการประยุกต์ใช้การเรียนรู้เชิงลึกกับโครงสร้างจุลภาคของตลาดที่สะอาดและมีแรงจูงใจที่ดี สถาปัตยกรรมสามบล็อกของมัน — CNN สำหรับคุณลักษณะเชิงพื้นที่ inception สำหรับรูปแบบเชิงเวลาแบบหลายสเกล LSTM สำหรับการพึ่งพาเชิงลำดับ — ทาบลงบนโครงสร้างของข้อมูลสมุดคำสั่งซื้อขายแบบจำกัดราคาอย่างเป็นธรรมชาติ

ข้อมูลเชิงลึกที่สำคัญไม่ใช่แค่ว่าโมเดลเชิงลึกสามารถเทียบเท่าหรือเอาชนะคุณลักษณะที่สร้างด้วยมือ แต่อคติเชิงอุปนัยของสถาปัตยกรรม — ฟิลเตอร์ 1×21 \times 2 ความขนานของ inception ความจำแบบ recurrent — เข้ารหัสความรู้เฉพาะทางที่แท้จริงเกี่ยวกับวิธีที่สมุดคำสั่งทำงาน นี่ไม่ใช่เครือข่ายเชิงลึกทั่วไปที่โยนลงบนข้อมูลทางการเงิน มันเป็นสถาปัตยกรรมที่ออกแบบรอบเรขาคณิตเฉพาะของสมุดคำสั่งซื้อขายแบบจำกัดราคา และหลักฐานที่น่าเชื่อถือที่สุดของมันไม่ใช่ตารางคะแนน FI-2010 ที่ผู้เขียนเองไม่ไว้วางใจ แต่เป็นผลลัพธ์การเรียนรู้แบบถ่ายโอนบนข้อมูล LSE หนึ่งปี

สำหรับผู้ปฏิบัติงาน DeepLOB เป็น baseline ที่แข็งแกร่งและองค์ประกอบที่มีประโยชน์ในการสร้าง สำหรับนักวิจัย มันแสดงให้เห็นว่าการออกแบบสถาปัตยกรรมที่รอบคอบ — ไม่ใช่แค่ขนาดของโมเดล — เป็นตัวขับเคลื่อนประสิทธิภาพบนข้อมูลทางการเงินที่มีโครงสร้าง เพียงจำไว้ว่าให้อ้างอิงตัวเลขจริง เฝ้าดูแบบแผนของป้ายกำกับ และถือว่าความแม่นยำในการจำแนกประเภทยังห่างไกลจากกำไรในการเทรดมาก


เอกสารอ้างอิง

  1. Zhang, Z., Zohren, S., & Roberts, S. (2019). DeepLOB: Deep Convolutional Neural Networks for Limit Order Books. IEEE Transactions on Signal Processing, 67(11), 3001-3012. arXiv:1808.03668

  2. Ntakaris, A., Magris, M., Kanniainen, J., Gabbouj, M., & Iosifidis, A. (2018). Benchmark Dataset for Mid-Price Forecasting of Limit Order Book Data with Machine Learning Methods. Journal of Forecasting, 37(8), 852-866. arXiv:1705.03233

  3. Briola, A., Bartolucci, S., & Aste, T. (2024). Deep Limit Order Book Forecasting (LOBFrame). arXiv:2403.09267

  4. Wallbridge, J. (2020). Transformers for Limit Order Books. arXiv:2003.00130

  5. Cont, R., Kukanov, A., & Stoikov, S. (2014). The Price Impact of Order Book Events. Journal of Financial Econometrics, 12(1), 47-88.

  6. Stoikov, S. (2018). The Micro-Price: A High-Frequency Estimator of Future Prices. Quantitative Finance, 18(12), 1959-1966.

  7. Nagy, P., Frey, S., Li, K., Sarkar, B., Vyetrenko, S., Zohren, S., Calinescu, A., & Foerster, J. (2025). LOB-Bench: Benchmarking Generative AI for Finance — an Application to Limit Order Book Data. ICML 2025. arXiv:2502.09172

  8. DeepLOB code (original in Keras/TensorFlow; the repository also provides a PyTorch port): github.com/zcakhaa/DeepLOB-Deep-Convolutional-Neural-Networks-for-Limit-Order-Books

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

ผู้เขียน

Eugen Soloviov
Eugen Soloviov

Trading-systems engineer

Trading-systems engineer building bots since 2017: cross-exchange arbitrage (connected up to 30 venues), cointegration-based pairs arbitrage across spot and futures, scalping, news and sentiment-driven strategies, trend algorithms, and portfolio management and balancing algorithms. Also builds sub-millisecond order execution, big-data warehouses, backtesting engines, AI agents, and trading interfaces (incl. open-source profitmaker.cc). Stack: JS/TS, Python, Rust/Zig/Go, DevOps, backend, frontend, architecture.

Newsletter

ก้าวนำหน้าตลาด

สมัครรับจดหมายข่าวของเราเพื่อรับข้อมูลเชิงลึกการเทรดด้วย AI เฉพาะ การวิเคราะห์ตลาด และการอัปเดตแพลตฟอร์ม

เราเคารพความเป็นส่วนตัวของคุณ ยกเลิกการสมัครได้ทุกเมื่อ