tanstaafl.dev

가장 빠른 마켓 데이터 파서 만들기

2020-08-16

옛날 옛적 HFT 바닥에 처음 발을 들이며 시작했던 일은 CME(시카고 선물 거래소)의 마켓 데이터 파서를 짜는 일이었다.

CME는 그때도 지금도 최대의 선물 옵션 시장이다. 잘 알려져 있지만 HFT 회사들은 거래소의 IDC에 직접 서버를 설치해서 마켓 데이터(호가, 거래량 등)를 빠르게 전송받는다. 당시는 CME가 FIX/FAST라는 새 마켓 데이터 포맷을 내놓아서 HFT 회사들이 한참 마이그레이션을 하고 있던 시점이었다. 회사에서는 이미 CME에서 제공한 C++ 레퍼런스 구현을 최적화해서 벤치마킹하고 있었고, 경쟁사보다 다섯 배 빠르다는 스웨덴 회사의 솔루션을 구입하는 쪽도 알아보고 있었다. 그때 나는 알고리즘 트레이더 여름 인턴이었는데, 시켜봐서 뭐 잘 나오면 좋고, 아니면 사서 쓰지 뭐 하는 마음으로 나한테 이런 프로젝트를 줬던 것 같다.

이 마켓 데이터 포맷은 key-value 쌍을 전송하는 바이너리 인코딩이었는데, 여기에 사용하는 스트리밍용 압축 알고리즘이 아주 악랄했다. 이 프로토콜의 스트리밍용 압축 알고리즘은, 비슷한 형태의 작은 패킷 데이터가 반복되어서 전송된다는 것을 이용한다. 거래소에서 보내오는 마켓 데이터의 대부분은 호가(예: 가격 x에 수량 y를 구매하려는 사람이 있음)와 거래(예: 가격 x에 수량 y 거래가 체결됨)다. 여기에 나노초 (혹은 마이크로초나 밀리초) 시간과 순차적으로 증가하는 일련번호, 기타 정보 등이 포함된다. 그런데 많은 경우 반복되는 정보들이 많다. 예를 들면:

황당한 것은 위의 예같은 규칙들이 프로토콜이 아니라, 이 규칙들을 정의하는 XML파일이 있고 이 파일은 매일 예고 없이 바뀔 수 있으며, 파서는 매일 아침 FTP에서 다운로드한 규칙 파일과 바이너리 스트림을 조합해서 데이터를 디코딩해야 한다는 것이었다. 이렇게 규칙이 복잡하니 이 파서들이 느린 것은 당연했다.

헌데 스펙을 훑어보고 나니 (운 좋게도) C++ 레퍼런스 구현은 삽질이라는 사실을 깨닫게 되었다. 주어진 XML을 일종의 프로그래밍 언어라고 생각하면, CME에서 제공한 레퍼런스 구현은 이 프로그래밍 언어를 구현한 인터프리터였다. 따라서 이 XML을 컴파일하는 컴파일러를 만들면 당연히 레퍼런스 구현보다 백배는 빠르게 돌아가겠지!

물론 나는 컴파일러 수업 한번 안 들어본 꼬꼬마였고 (아 뭐 지금도 잘 모르는 것은 마찬가지..) 당시에는 LLVM을 들어본 적도 없었다. 그래서 나는 XML을 읽어들여 C++ 코드를 생성하는 파이썬 프로그램을 짜기로 했다. 아마 이전 학기 프로젝트 중 하나에서 비슷한 일을 했었기에 쉬운 선택이었던 것 같다.

이때쯤 스웨덴 회사에서 트라이얼용 라이센스와 설명서를 보내왔는데, 여기도 똑같이 코드 제너레이션 하고 있더라. (...) 그래서 용기백배해서 열심히 구현하고 최적화했고, 결국 스웨덴 회사 물건보다 50% 빠른 결과를 내서 내 라이브러리를 프로덕션에 넣기로 했다는 이야기.

이 프로젝트 결과가 잘 나와서 무난하게 리턴 오퍼를 받게 되었고, 달러에 눈이 먼 나는 (...) 홀린 듯이 이 바닥으로 뛰어들게 되었다. 그리고 지금까지...

처음으로