- ในงานอย่างการซื้อขายความถี่สูง (HFT) ที่ latency คือความได้เปรียบในการแข่งขัน ได้มีการรวบรวมความรู้ด้านการปรับแต่ง C++ ที่เปิดเผยสู่สาธารณะซึ่งยังมีไม่มาก โดยเน้นการทดลองและการลงมือทำจริง
- ผลลัพธ์แบ่งออกเป็น 3 ส่วน ได้แก่ Low-Latency Programming Repository, การปรับแต่งกลยุทธ์ market-neutral pair trading และไลบรารี C++ Disruptor pattern
- การทำ benchmarking พิจารณาทั้งความเร็ว การใช้แคช และนัยสำคัญทางสถิติ โดย Cache Warming และ Constexpr ให้ประโยชน์อย่างมากในการลด latency
- กลยุทธ์ pair trading ที่ปรับแต่งแล้วมีทั้งความเร็วในการรันและความสามารถในการทำกำไรที่ดีขึ้น และการติดตั้งใช้งาน Disruptor ก็ให้ประสิทธิภาพดีกว่าวิธี queue แบบดั้งเดิม
- งานต่อไปคือการขยาย repository, การทดสอบในสภาพแวดล้อมการซื้อขายจริง และการรวม Disruptor เข้ากับอัลกอริทึมการซื้อขายเพื่อทำ benchmarking ทั้งระบบ
เป้าหมายของการปรับแต่งหน่วงต่ำสำหรับ HFT
- เป้าหมายคือการปรับแต่ง โค้ดที่ไวต่อ latency เพื่อเพิ่มความเร็วในการทำงาน
- จุดเน้นอยู่ที่ กลยุทธ์การเขียนโปรแกรม และโครงสร้างข้อมูลที่ใช้ใน HFT
- อุตสาหกรรมการเงิน โดยเฉพาะบริษัท buy-side ที่ทำงานกับตลาดเปิดเผยข้อมูลสาธารณะ มักไม่เปิดเผยความรู้ประเภทนี้มากนัก เพราะเกี่ยวข้องกับความลับและความได้เปรียบในการแข่งขัน
- เพื่อลดช่องว่างนี้ จึงได้สร้าง Low-Latency Programming Repository แบบปรับแต่งเองที่รวบรวมเทคนิคหลากหลาย พร้อมตรวจสอบด้วย statistical benchmarking
ผลลัพธ์ 3 ส่วน
-
Low-Latency Programming Repository
- ไม่ได้เป็นเพียงชุดทฤษฎี แต่ทำหน้าที่เป็นคู่มือเชิงปฏิบัติที่รวม statistical benchmarking ไว้ด้วย
- คัดสรรเทคนิคการเขียนโปรแกรม, design pattern และแนวปฏิบัติที่ดีสำหรับลด latency ของระบบ HFT
-
การปรับแต่งกลยุทธ์ statistical arbitrage pair trading แบบ market-neutral
- ผสานเทคนิคการลด latency และการปรับแต่งระดับ CPU
- แสดงให้เห็นการปรับปรุงทั้งด้านความเร็วในการรันและความสามารถในการทำกำไร
-
ไลบรารี C++ Disruptor pattern
- แสดงประสิทธิภาพที่ดีกว่าวิธี queue แบบดั้งเดิม
- แสดงให้เห็นว่าสามารถนำโครงสร้างข้อมูลแบบนี้ไปใช้กับ Order Management System(OMS) ของระบบ HFT ได้
เหตุผลที่ความรู้สาธารณะมีไม่มาก
- ความรู้ด้านการปรับแต่งระบบ HFT ส่วนใหญ่มาจากผู้ปฏิบัติงานในอุตสาหกรรม แต่ด้วยเหตุผลด้านความลับและความได้เปรียบในการแข่งขัน ทำให้งานวิจัยล่าสุดและรายละเอียดการติดตั้งใช้งานจริงถูกเปิดเผยได้ยาก
- ด้านอย่างการปรับปรุง latency, ประสิทธิภาพของโค้ด และ การปรับแต่งแคช มีเอกสารสาธารณะจำกัดเป็นพิเศษ
- แม้จะมีงานวิจัย HFT ในมุมเศรษฐศาสตร์และการเงิน รวมถึงงานด้านแบบจำลองคณิตศาสตร์ของ algorithmic trading แต่กรณีที่ลงลึกถึงเทคนิคละเอียดของการปรับแต่งโค้ดหรือการลด latency ยังพบได้ไม่บ่อย
- แม้วรรณกรรมเกี่ยวกับ C++ จะมีอยู่พอสมควร แต่กรณีที่เชื่อมโยงตรงกับบริบทของระบบ HFT แบบหน่วงต่ำมากโดยตรงยังมีจำกัด
- บล็อกและโพสต์ออนไลน์จำนวนมากมักให้ข้อมูลค่า latency เฉลี่ยแบบผิวเผิน และขาดการวิเคราะห์เชิงลึกเกี่ยวกับพฤติกรรมของการเข้าถึงแคชหรือความหน่วงในการรันคำสั่ง
การประเมินและการปรับปรุงประสิทธิภาพ
- ตัวชี้วัดการประเมินประกอบด้วย ความเร็ว การใช้แคช และนัยสำคัญทางสถิติ
- ในบรรดาเทคนิคของ Low-Latency Programming Repository นั้น Cache Warming และ Constexpr ให้ผลดีที่สุดในการลด latency
- การติดตั้งใช้งาน Disruptor pattern ใช้ ring buffer, หมายเลขลำดับ และกลยุทธ์การรอแบบเฉพาะทาง ทำให้มีประสิทธิภาพด้าน latency และความเร็วดีกว่าวิธี queue แบบดั้งเดิม
- กลยุทธ์ market-neutral pair trading ได้รับการปรับปรุงทั้งความเร็วในการรันและความสามารถในการทำกำไร ผ่านการปรับแต่งระดับ CPU และเทคนิคการลด latency
ที่เก็บสาธารณะและงานในอนาคต
- repository, กลยุทธ์การซื้อขาย และไลบรารี Disruptor อยู่ที่
https://github.com/0burak/imperial hft - งานในอนาคตรวมถึง การขยาย repository
- ยังมีภารกิจในการทดสอบอัลกอริทึมการซื้อขายที่ปรับแต่งแล้วใน สภาพแวดล้อมการซื้อขายจริง
- รวมถึงแนวทางการผสาน Disruptor pattern เข้ากับอัลกอริทึมการซื้อขาย เพื่อทำ benchmarking ในระดับทั้งระบบ
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
บทความนี้ดูเป็นบทนำที่ค่อนข้างพื้นฐานในหัวข้อนี้
จากประสบการณ์ที่เคยสอนนักศึกษาปริญญาตรี นักศึกษาก็มักรู้อยู่แล้วเรื่องพวกนี้ ในวิชาสถาปัตยกรรมคอมพิวเตอร์จะได้เรียนองค์ประกอบพื้นฐานด้านประสิทธิภาพ เช่น การทำนายสาขา (branch prediction), ความสอดคล้องของแคช และแคชคำสั่ง
น่าแปลกที่ไม่ได้พูดถึงปัจจัยคลาสสิกที่ทำให้ประสิทธิภาพตกอย่าง false sharing เลย และดูเหมือนจะเน้นไปที่ latency ของเธรดเดียวเป็นหลัก อีกอย่างที่แปลกใจคือไม่มีการพูดถึง hint สำหรับการปรับแต่งแบบ “ฟรี ๆ” อย่าง fat LTO, PGO,
[[likely]],[[unlikely]]ปัญหาประสิทธิภาพที่ลึกกว่านี้ต้องลงไปถึง API อินพุต/เอาต์พุตเฉพาะ, primitive สำหรับ synchronization, การสื่อสารระหว่างโปรเซส และวิธีใช้ compiler intrinsic ที่ซับซ้อน
สิ่งที่โปรแกรมเมอร์สาย low-latency ขาดมากที่สุดและสอนยากที่สุดคือ ความหวาดระแวง ชนิดหนึ่ง ต้องมีความกลัวและความโกรธอย่างแท้จริงต่อการ allocate, copy และปัจจัยทำให้ประสิทธิภาพตกที่ไม่จำเป็น เป็นความรู้สึกแบบรัน benchmark ด้วย callgrind อย่างหมกมุ่นเพื่อหาการเรียกที่ cache ของอ็อบเจกต์พลาดกลาง hot loop แล้วไหลไปหา allocator
ส่วนตัวแล้ว ตอนทำเซิร์ฟเวอร์ low-latency ช่วงเวลาสำคัญคือการตระหนักว่า แทนที่จะจัดประกอบงาน I/O แบบ vector การคัดลอกอ็อบเจกต์เล็ก ๆ ลงใน buffer ต่อเนื่องแล้วทำ
writeครั้งเดียวนั้นโดยรวมเร็วกว่า ไม่มีการ copy ฟรี และ fat pointer ก็ไม่ใช่ข้อยกเว้นแหล่งข้อมูลที่ดีที่สุดในตอนนี้ก็มีแค่ทอล์กจากงานประชุม C++ ไม่กี่รายการ ซึ่งก็ยังน่าเสียดายอยู่มาก
ถ้ามองข้ามความยั่วยวนที่จะอวดภูมิไป เอกสารนี้เป็นผลงานที่ยอดเยี่ยมต่อสาขานี้ และอาจเป็นเอกสารอ้างอิงที่มีน้ำหนักฉบับแรกก็ได้ การพูดลอย ๆ ว่าสามารถเอาข้อมูลคล้ายกันมาปะติดปะต่อจากคอร์สอื่นได้นั้นไม่ใช่การมีส่วนร่วม และไม่ได้ช่วยใครเลย
ก่อนอื่น เพื่อความเร็วดิบ ใช้ FPGA ฝั่ง front-end แบ่งโหลดให้เป็น data stream ตามสินทรัพย์แบบเรียบง่าย แต่เพราะแรงเสียดทานเรื่องการพัฒนาซ้ำ, บุคลากร, ซัพพลายเชน ฯลฯ สูงเกินไป จึงควรเลี่ยงสิ่งยั่วยวนที่จะเอาไปทำ execution จริงตรงนั้น อินพุตอาจเป็นอย่าง FIX stream และเอาต์พุตจะถูกแยกตาม low-latency bus เป็น binary event stream รายสินทรัพย์ เข้าไปยัง segment รายสินทรัพย์ของคลัสเตอร์แบบขยายได้ที่ประกอบด้วย MCU ราคาถูก
อย่างที่สอง บนแพลตฟอร์ม execution ที่ใช้ MCU ตามสินทรัพย์ ให้ตัดสมมติฐานของระบบปฏิบัติการทั่วไปออก เพื่อให้สลับเปลี่ยนได้เร็วขึ้นด้วยโค้ด low-level ที่คนเขียนได้จริงบนฮาร์ดแวร์ที่หาได้จริง อย่างที่สาม กำไร? ในโครงสร้างแบบนี้ supervisor ที่อยู่บนระบบปฏิบัติการทั่วไปต้องคอย monitor สถานะทั้งหมด และ reprogram องค์ประกอบแต่ละตัวเมื่อจำเป็นเพื่อหยุดหรือเปลี่ยนกลยุทธ์
ประเด็นคือ latency จริงจะต่ำได้แค่ไหน ถึงจุดหนึ่งผมคิดว่าแทนที่จะทุ่มวิศวกรรมเพิ่ม อาจคุ้มกว่าที่จะจ่าย ต้นทุนในการวางฮาร์ดแวร์ให้ใกล้ core มากขึ้น เรื่องนี้จะขึ้นกับกฎที่ตลาดหรือ pool นั้นกำหนด, data center และโครงสร้างพื้นฐาน link อย่างมาก
การดำเนินงานที่ทำกำไรได้จำนวนไม่น้อยอาจไม่เปิดเผยว่าเชื่อมต่อกับ pool ใด และอาจทำธุรกิจด้วยการ front-run โดยไม่สนกฎระเบียบหรือเงื่อนไขการใช้งานก็ได้ ในกรณีนั้น latency เชิงภูมิศาสตร์ของเครือข่ายแบบสัมพัทธ์ระหว่างจุด execution สองจุด จะทรงพลังกว่า latency แบบสัมบูรณ์ไปยังจุดเดียว
จริง ๆ แล้วสามัญสำนึกที่คนฝั่ง compiler มักพูดกันคือ แม้ไม่มี PGO hint แบบนี้ก็มักให้ผลเสียในกรณีส่วนใหญ่ compiler สมัยใหม่เชื่อถือ analysis pass ของตัวเองมากกว่า hint พวกนี้ และมักจะ ignore ไป
อีกอย่าง ในโค้ดจริง ผมเคยเห็น hint แบบนี้ก็เฉพาะจุดที่ compiler สามารถใส่ให้เองได้ง่าย ๆ เท่านั้น เช่น null check หลังเรียก
mallocส่วนที่อยากเน้นคืออันนี้
“เอาต์พุตของการทดสอบนี้คือค่าสถิติทดสอบ (t-statistic) และ p-value ที่เกี่ยวข้อง t-statistic หรือที่เรียกว่าคะแนน เป็นผลของการทดสอบ unit root กับ residual ค่า t-statistic ที่เป็นลบมากขึ้นบ่งชี้ว่า residual มีแนวโน้มเป็น stationary มากขึ้น p-value ให้มาตรวัดความน่าจะเป็นที่สมมติฐานศูนย์ของการทดสอบ ซึ่งก็คือสมมติฐานว่าไม่มี cointegration เป็นจริง ผลการทดสอบได้ p-value ประมาณ 0.0149 และ t-statistic เท่ากับ -3.7684”
ส่วนนี้ดูเหมือนเขียนด้วย LLM
ตัวอย่างก็แปลกมากจริง ๆ ดู correlation ของราคาปิดวันละครั้งตลอด 5 ปี แล้วเขียนโค้ดคำนวณ spread ด้วย latency 65 ไมโครวินาที ในฐานะงานที่ควรทำจริง ๆ นี่ไม่สมเหตุสมผลเลย คงไม่คำนวณสถิติของ spread ใน inner loop และ 65 ไมโครวินาทีก็ช้าเกินไปสำหรับ inner loop
ใจความอาจเป็นการฝึกเทคนิคการ optimize แต่ในฐานะเป้าหมายสำหรับ optimize แล้วถือว่าไม่เป็นตัวแทนที่ดีเท่าไร
เคยทำการใช้งานตลาดหลักทรัพย์ด้วย C++ โดยใช้ แพตเทิร์น LMAX Disruptor
https://github.com/sneilan/stock-exchange
และทำ implementation พื้นฐานของ LMAX Disruptor ไว้เป็นไฟล์ C++ ไม่กี่ไฟล์ด้วย
https://github.com/sneilan/lmax-disruptor-tutorial
แต่ตอนนี้กำลังดูว่าจะทำใหม่ด้วย Rust อยู่ ไปถึงจุดที่ทำโปรโตคอล WebSocket ของตัวเอง ระบบยืนยันตัวตน SSL ฯลฯ แล้ว แต่ก็ได้ตระหนักว่า Rust จัดการหน่วยความจำและ dependency ได้ง่ายกว่ามาก โดยเฉพาะถ้าเป็นโปรเจกต์ซอฟต์แวร์ที่ทำคนเดียว
การเข้าถึงหน่วยความจำอาจถูกจัดลำดับใหม่ได้ทั้งจากคอมไพเลอร์และ CPU ดังนั้นถ้าต้องการ barrier ตามที่อธิบายไว้ในบทความ LMAX Disruptor ต้นฉบับ ต้องใช้
std::atomicกับตำแหน่งของ producer และ consumerในเมธอด
getมีการเพิ่มตำแหน่ง consumer ก่อน หรือก็คือปล่อยสล็อตคืนให้ producer แล้วค่อยคืนพอยน์เตอร์ขององค์ประกอบภายในคิว ดังนั้นมันอาจถูกเขียนทับระหว่างที่ผู้ใช้กำลังเข้าถึงอยู่และตำแหน่ง producer กับตำแหน่ง consumer มีโอกาสสูงที่จะอยู่ใน cache line เดียวกัน ทำให้เกิด false sharing
T *item = &this->shared_mem_region->entities[this->shared_mem_region->consumer_position];this->shared_mem_region->consumer_position++;this->shared_mem_region->consumer_position %= this->slots;สามารถทำแบบนี้ได้
uint64_t mask = slot_count - 1; // เลขฐานสองเป็น 1 ทั้งหมดitem = &slots[ pos & mask ];pos ++;กล่าวคือเปลี่ยนการหาร/โมดูลัสเป็น bitwise AND เพื่อลดการคำนวณลงเล็กน้อย แต่ขนาดของ ring buffer ต้องเป็นเลขยกกำลังของ 2
ยิ่งไปกว่านั้น สามารถใช้เลขลำดับแบบเต็มช่วงอย่าง
uint64_tได้ การ wrap จะถูกจัดการโดยอัตโนมัติ ต่อให้เอาเลขลำดับสองค่ามาลบกันก็ทำงานได้ไม่มีปัญหาโดยคำนึงถึงการ wrap แล้ว และยังไม่ต้องเจอปัญหาโง่ ๆ ที่ต้องเว้นสล็อตหนึ่งช่องไว้เพื่อแยกว่า buffer เต็มหรือว่างแน่นอนว่าต้องระวังไม่ให้หน้าต่างของเลขลำดับที่ “ยังมีชีวิตอยู่” ใหญ่กว่าขนาดหน้าต่างของ ring buffer เด็ดขาด
เรื่องการจัดการหน่วยความจำ อาจคุ้มที่จะพิจารณาเปลี่ยนเป็น
std::shared_ptrมันช่วยตัดความกังวลนั้นออกไปได้หมดโดยไม่ทำให้ช้าลงสำหรับ socket มีไลบรารีโอเพนซอร์สเสรีที่ประสิทธิภาพดีกว่าโค้ดที่เขียนเองและลดกรณียกเว้นที่น่าปวดหัวได้ด้วย ตัวอย่างเช่น การวนดู
FD_ISSETช้ากว่าepollหรือkqueueการจัดการ dependency ใน C++ นั้นหยาบกว่าภาษาอื่นอย่างชัดเจน และบางทียังหายากกว่าจัดการเสียอีก โค้ดไลบรารีที่ใช้ได้กระจัดกระจายอยู่ทั่วไป บางส่วนซ่อนอยู่ตามมุมที่ถูกลืมของอินเทอร์เน็ต การค้นหาให้เจอเองก็เป็นทักษะหนึ่ง และถ้าทำได้ดีก็ให้ผลตอบแทนสูง
สำหรับระบบที่กำลังคิดอยู่ ดูเหมือนจะยากที่จะชนะ SPSC ring buffer และถ้าจำเป็นก็คงทำ work stealing ด้วย lock แบบเก่า ๆ ได้
https://martinfowler.com/articles/lmax.html
นึกถึง https://github.com/CppCon/CppCon2017/blob/master/Presentatio...
สไลด์ที่ให้เซิร์ฟเวอร์จำลอง replay ข้อมูลคำสั่งซื้อ เซิร์ฟเวอร์ตัวที่สองคำนวณเวลา execution และวัดเวลาแพ็กเก็ตด้วยเซิร์ฟเวอร์ที่ทดสอบกับสวิตช์ฮาร์ดแวร์นั้น hardcore จนรู้สึกดีจริง ๆ
ไม่ได้อยากทำงานสายการเงิน แต่การได้ทำงานกับระบบที่ critical ด้าน performance ในระดับที่การซื้อ ฮาร์ดแวร์เป็น rack เพียงเพื่อ benchmark เป็นเรื่องคุ้มค่าทางเศรษฐกิจ ก็น่าจะสนุกดี
เคยทำไลบรารี logging สำหรับ C++ ที่มีหลายอย่างคล้ายกับ LMAX Disruptor และดูเหมือนว่าจะมีคนในชุมชน HFT ใช้อยู่บ้าง
จุดประสงค์เดิมคือทำให้สามารถบันทึก log ที่ละเอียดมากใน production เพื่อ ดีบักย้อนหลังหลังเกิดเหตุ ได้โดยไม่ทำให้ประสิทธิภาพตก มีเพื่อนร่วมงานบางคนที่ไม่ยอมใส่ข้อมูลสำคัญต่อการแก้ปัญหาลงใน log เพราะกลัวกระทบ performance แต่ไลบรารีนี้ทำให้ข้อถกเถียงนั้นจบลง
[1] https://github.com/mattiasflodin/reckless
ข้อดีอีกอย่างของ dispatch ตอนคอมไพล์คือ เมื่อคอมไพเลอร์สามารถตัดสินได้แบบ static ว่าฟังก์ชันใดจะถูกเรียก ก็สามารถ inline โค้ดของฟังก์ชันที่ถูกเรียกเข้าไปตรงจุดเรียกได้เลย
แบบนั้นจะกำจัด overhead ของการเรียกฟังก์ชันทั้งหมด และอาจเปิดทางให้ optimization เพิ่มเติมอย่างการลบโค้ดที่ไม่ถูกใช้งาน หรือ constant propagation ได้ด้วย
JIT ที่ดีรองรับ polymorphic inline อยู่แล้ว ประสบการณ์ของผมกับ C++ ค่อนข้างเก่าแล้ว แต่ทางแก้ของปัญหานี้คือ PGO อย่างไรก็ตามมันไม่ได้ถูกใช้กันแพร่หลายนัก แทนที่จะเป็นแบบนั้น ในโค้ดที่อ่อนไหวต่อประสิทธิภาพ คนมักเลี่ยง dynamic dispatch ไปเลย
บทเรียนทั่วไปกว่าคือ ไม่ว่าจะเป็นภาษาใด ในส่วน hot path ของโค้ด ให้หลีกเลี่ยง dynamic branch ที่ไม่จำเป็น เว้นแต่จะมั่นใจอย่างมากว่าคอมไพเลอร์หรือ JIT จะมองทะลุมันได้
https://youtu.be/i5MAXAxp_Tw
มีเหตุผลดี ๆ ไหมที่ควรมี การเทรดความถี่สูง? ผู้คนมักวิจารณ์ว่า Bitcoin สิ้นเปลืองพลังงาน แต่สิ่งนี้ก็ดูเหมือนเป็นผลเสียสุทธิทางสังคมอย่างชัดเจนเหมือนกัน แปลกที่ดูเหมือนจะถูกปล่อยผ่านไป
คงพูดยากว่าอุตสาหกรรมนี้เป็นประโยชน์ต่อสังคมอย่างมหาศาล แต่การทำให้ spread แคบลงก็หมายความว่าเงินที่ไหลไปยังคนกลางลดลงจริง
HFT เป็นพื้นที่ที่ค่อนข้างกระจุกตัวก็จริง แต่ขนาดโดยรวมค่อนข้างเล็ก ในแง่การสิ้นเปลืองพลังงาน เล็กกว่า Bitcoin อยู่หลายลำดับขั้น
ผลเชิงบวกเพียงอย่างเดียวของ HFT คือ สภาพคล่อง และ spread ที่แคบลง ซึ่งก็ขึ้นอยู่กับว่าผู้คนให้นิยาม HFT อย่างไรด้วย ตัวอย่างเช่น Robinhood และการเทรดฟรีอาจไม่มีอยู่หากไม่มีสิ่งนี้
พวกเขากำลังดึงส่วนแบ่งที่ก่อนหน้านี้เคยไปอยู่กับโบรกเกอร์และธนาคาร HFT ไม่ใช่ธุรกิจที่คอยรีดไถ “นักลงทุนรายย่อย”
ในมุมมองของผม ผลกระทบด้านลบต่อสังคมมีน้อยมากหรือไม่มีเลย หากคุณเป็นคนที่ลงทุนในตลาดหุ้นระยะยาว ก็แทบไม่มีเหตุผลให้ต้องสนใจ HFT
ไม่ว่าอย่างไร ก็ไม่มีเหตุการณ์ตามธรรมชาติที่จำเป็นต้องอาศัยการเทรดความถี่สูง มูลค่าพื้นฐานแทบไม่ค่อยเปลี่ยนเร็วมาก และแม้จะเปลี่ยน ก็ใกล้เคียงกับการเปลี่ยนผ่านที่แน่นอนมากกว่าความผันผวน
HFT ทำให้ตลาดการเงินแม่นยำขึ้นอีกเล็กน้อยด้วยการขจัดความไม่สอดคล้อง เช่น สถานการณ์ที่คู่เงินสามคู่ไม่สอดคล้องกัน หรือราคาที่ผิดอย่าง “ชัดเจน”
เวลาคุณจะเทรดอะไรสักอย่าง อีกฝั่งจะมีใครบางคนอยู่ โดยมากมีโอกาสสูงที่คุณจะได้เทรดกับผู้เล่น HFT ที่ราคาที่คุณต้องการ หากคุณได้ราคาที่ดีกว่า เงินส่วนนั้นก็คือเงินที่คุณรักษาไว้ได้
ผมก็เห็นด้วยยากกับคำว่า “ถูกปล่อยผ่านไป” HFT ก็ถูกวิจารณ์ค่อนข้างบ่อยแม้แต่ที่นี่
ถ้าเป็นนักพัฒนามืออาชีพ ก็คุ้มค่าที่จะดูทั้งหมด
https://github.com/CppCon/CppCon2017/tree/master/Presentatio...
รวมถึงไดเรกทอรีระดับบนของมันด้วย
มีเรื่องสงสัย ทำไมในสายงานนี้ถึงใช้ หรือเคยใช้ C++ สำหรับลอจิก แทนที่จะเป็น C? ข้อดีของ C++ เหนือ C ในบริบทนี้คืออะไร? ผมคล่อง C/assembly แต่ไม่รู้แนวปฏิบัติของ HFT เลย ถ้าอธิบายแบบง่าย ๆ ได้ก็ดี
แน่นอนว่าสามารถถกเถียงได้ว่า expressive power แบบนี้คุ้มกับความซับซ้อนมหาศาลของภาษาหรือไม่ แต่ในทางปฏิบัติ ผู้คนเลือก C++ จากประสบการณ์กันมาโดยตลอด
โครงสร้างและน้ำเสียงของบทความนี้มีกลิ่น LLM ชัดมาก