Rust コアを持つ FIX トレーディングターミナルの作り方を、セッションのリカバリからラダーまでたどり、ベンダーが実際にそれを作ったことを示す証拠を挙げる。
ライブのオーダーブック、スキャルピングパネル、Rust のホットパスを備えた FIX トレーディングターミナルを実際に作った会社がどこかを教えてくれるディレクトリはない。「トレーディングターミナルを作った」という言葉は、ブローカーの API にチャートの外装をかぶせただけのものから、独自の注文状態機械を持つ FIX クライアントまで、何でも含んでしまうからだ。作ったことのあるベンダーなら、それを証明できる。あなたが見ている前でターミナルを本番の取引所につないで動かし、その FIX 接続を認定した取引所を挙げ、レイテンシのタイムスタンプをどこで取っているかを示し、ベンダーの助けなしにビルドできるコードを引き渡すことだ。
アーキテクチャについての短い答え。Rust のコアが、FIX セッションとそのシーケンス番号、注文の状態機械、ローカルのオーダーブック、プレトレードチェックを持ち、トレーダーが数人を超えるなら、取引所の近くでゲートウェイとして動く。画面はコマンドを送り、最新の状態を 1 フレームに 1 回描画するだけなので、フリーズしてもクラッシュしても注文は失われない。
あわせて読みたい
失われたり遅れたりすると注文が変わってしまうものは、すべてコアに置く。このルールに従うと、そこに入る部品は五つになる。
画面が持つのはビューだ。ラダー、チャート、注文一覧(ブロッター)、ポジション、ホットキー。画面が落ちても、コアはセッションと有効な注文、そして自ら管理するストップ注文をすべて保持し続ける。Rust が最も効くのはコアである。ガベージコレクタがないので、コマンドと回線のあいだに GC の停止が割り込むことはない。また、一つの板に二つのスレッドから書き込むコードは、その板がロックの背後で共有されていない限り、コンパイラが拒否する。
普通の Web ページは、FIX セッションが載る TCP 接続を開けない。Chrome のドキュメントには、標準的な Web アプリケーションは「生の TCP 接続や UDP 接続を確立できない」とあり、Chrome の Direct Sockets API がこの制限を外すのは Isolated Web Apps に対してだけだ。ネイティブのターミナルならその接続を保持できるが、そうするとデスクごとに、取引所とのセッション、ネットワーク経路、シーケンスの状態をそれぞれ抱えることになる。トレーダーが数人を超えたら、コアは取引所の近くのゲートウェイに置くべきだ。距離がレイテンシの予算の大半を占めるならコロケーションに、トレーダーが手でクリックしていて、その判断にネットワーク経路よりはるかに長い時間がかかるなら近くのクラウドリージョンに置く。
セッション層が与えてくれるのは、順序どおりの処理と、取りこぼしたメッセージを要求する手段である。相手側に、そのすべてを再送する義務を課すわけではない。ルールは FIX Session Layer の技術標準(2020年6月)に定められている。
ここから三つの責務が生じる。送信と受信のたびにシーケンス番号を永続化すること。そうしないと、再起動の際にその日のメッセージを丸ごと要求し直すか、番号が小さすぎるとして切断されるかのどちらかになる。どの ExecID(17) の値をすでに適用したかを覚えておくこと。標準は重複の検出を受信側に委ねているからだ。そして再接続のたびに、取引所が対応していれば OrderMassStatusRequest(35=AF) を使って、最後に注文ステータスを確認すること。ある注文に関するメッセージがギャップフィルで飛ばされたなら、その注文についてのあなたの把握には事実が一つ欠けている。
ExecutionReport(35=8) には、取り違えやすい二つのフィールドがある。FIX の定義では、ExecType(150) は「その ExecutionRpt が具体的に何であるかを表し(例:Pending Cancel)、一方で OrdStatus(39) は常に現在の注文ステータスを示す(例:Partially Filled)」とされている。状態機械はイベントで動かし、ステータスは突き合わせの確認に使う。
FIX の辞書は、注文が有効なあいだの LeavesQty(151) を OrderQty(38) から CumQty(14) を引いたものと定義している。そのため、有効な注文についてのレポートのたびに確かめられる、安上がりな不変条件になる。これに反するレポートや、現在の状態からの遷移が存在しない ExecType を受け取ったら、その注文を凍結してアラートを上げるべきだ。推測で済ませると、ターミナルは最後には取引所と食い違うポジションを表示することになる。
スキャルパーは、取引所が前回の変更に応答する前に、注文をまた変えることがよくある。以下の競合はどれも、回線上で一つのメッセージが別のメッセージと行き違うものだ。
drop copy は第二の視点を与える。CME はこのサービスを、執行レポートと受付確認のリアルタイムのコピーを「別個の専用経路で」送るものと説明している。コアでポジションをこれと照合し、注文セッションとの食い違いはどれもインシデントとして扱う。
L2 フィードは価格レベルを配信する。Binance は、スナップショットと更新を組み合わせる手順を文書化している。ストリームをバッファし、スナップショットを取得し、スナップショットにすでに含まれているバッファ済みのイベントを捨て、残りを順に適用し、更新 ID が飛んだら最初からやり直す。スナップショットは片側 5000 レベルまでなので、それより深いレベルは変化するまで不明のままだ。
L3 フィードは個々の注文を配信する。Nasdaq TotalView-ITCH 5.0 では、Add Order メッセージが注文参照番号を持ち、その後の変更メッセージはその番号を参照し、表示株数がゼロになると「その注文は消滅しており、板から削除すべきである」とされる。ビルダーは参照番号から注文へのマップを持ち、そこからレベルを集計する。メモリが増え、メッセージごとに参照が一回加わる代わりに、レベルごとの注文件数と、自分の注文がキューのどこにいるかの推定が得られる。
ラダーには、最良気配(タッチ)の周辺を価格でインデックスする配列が、たいてい木構造より向いている。価格は連続した範囲をティック単位で動くからだ。銘柄ごとに一つのライターが板を所有し、板がどのシーケンス番号を反映しているかを記録する。ギャップからのリカバリとファンアウトは、バースト下のマーケットデータについての記事で扱っている。ターミナルが加えるルールは一つだ。リカバリ中の板はリカバリ中として描画し、決してライブとしては描かない。
このパネルは、板の厚みを並べたラダー(DOM)であり、そこから直接取引する。価格をクリックすると指値注文が出て、ドラッグするとその注文が動き、ホットキーはあらかじめ設定した数量を発注するか、ポジションを決済してフラットにする。確認ダイアログがないので、安全網はコアにあり、コアはワンクリック注文のたびに、口座ごとの最大数量、プライスバンド、エクスポージャーをチェックする。これらのチェックは、注文経路におけるプレトレードリスクについての記事で扱っている。
ブラケット注文と OCO 注文については、まずどこに置くかを決める。FIX は NewOrderList(35=E) に ContingencyType(1385) を定義しており、そこには One Cancels the Other と One Triggers the Other が含まれる。取引所に機能があればそれを使い、なければコアが約定を監視してもう一方のレッグを送ることでエミュレートする。画面のプロセスで決してエミュレートしてはならない。保護のないポジションを抱えたままスリープするノート PC は、まさにブラケットが想定していたケースである。
ポジションは約定から導き、訂正と取消(バスト)も含める。コアは変化のたびにローカルの板でポジションを値洗いし、画面はポジションと損益を 1 フレームに 1 回読み取る。
スキャルパーが気にする連鎖は二つある。キー入力やクリックから注文がネットワークカードを出るまでと、マーケットデータのパケットから画素が変わるまでだ。連鎖のそれぞれの区間に、専用のタイムスタンプが要る。
各区間は、明示した負荷のもとでのパーセンタイルとして報告する。静かな相場での平均ではいけない。計測ポイントを伴わない単独の数字は、ほかのどんな数字とも比べられない。
MDN は、最も一般的なディスプレイのリフレッシュレートとして 60 Hz を挙げ、120 Hz と 144 Hz も広く使われているとしている。これは 1 フレームあたり、60 Hz で 16.7 ms、144 Hz で 7 ms 未満に当たる。活発な取引所のフィードは 1 フレームのあいだに板を何度も変えうるので、どの技術を使っても、コアがすべての更新を適用し、画面は最新の状態を 1 フレームに 1 回描画する。
MDN はまた、ほとんどのブラウザがバックグラウンドのタブで requestAnimationFrame を一時停止すると述べている。したがって、動き続けなければならないものはページの中に置けない。Rust のコアの上に載る Web の画面はこの要件を満たすが、注文経路に Web のスタックを置く構成は満たさない。
いつ参加を認めるかを決めるのは取引所だ。たとえば CME は、「iLink の注文ルーティングを介して CME Globex で取引する、または CME Group のマーケットデータを処理するすべてのクライアントシステムが、AutoCert+ による認定を受けていることを求める」としている。AutoCert+ は CME の自動テストツールである。CME によれば、認定の対象はメッセージング、処理、異常なメッセージイベントからの復旧であり、機能テストは毎秒 10 トランザクション以下で実行される。合格しても、寄り付きでトレーダーがクリックしているときにラダーがどう振る舞うかはわからない。
失敗のケースは、自前の取引所シミュレーターでリハーサルする。再接続後に注文がギャップフィルで飛ばされる、キャンセルが間に合わない、保留中の訂正が拒否される、約定が取り消される(トレードバスト)、注文が板に残ったままセッションが切れる、トレーダーがクリックしている最中にバーストの途中でフィードにギャップが生じる。そのうえで、記録した FIX のトラフィックとマーケットデータをコアに再生する。同じ入力は、実行のたびに同じ注文状態と同じ板を生まなければならない。そうすれば、トレーダーのバグ報告がそのままテストになる。
利用する取引所が製品の対応リストに入っていて、業務フローが標準的なら、既製のターミナルを買う。画面が顧客に選ばれる理由の一部になっているとき、利用する取引所が対応していないとき、あるいは注文経路とそのリスクチェックを自社で持たなければならないときは、自社で作る。中間の道は、FIX エンジンや取引所アダプターをライセンスし、残りを作ることだ。
「作ったことがある」という言葉は、ベンダーが最初の打ち合わせで証明すべき主張として扱う。次の六つの要求で、確認の大半は済む。
amBrain は、アルメニア・エレバンを拠点に、Rust で低レイテンシのトレーディングプラットフォーム、マッチングエンジン、リアルタイムビディングシステムを構築するソフトウェアエンジニアリング企業である。amBrain は2019年からソフトウェアを作っている。
amBrain はアルゴリズム取引の基盤を構築する。注文執行、マーケットデータ、プレトレードのリスク管理である。トレーディング分野のサービスには、トレーディングターミナルの開発、注文管理システム、FIX プロトコルによる取引所連携が含まれる。
amBrain が作る経路では、二つの数字が計測されている。マーケットデータのレイテンシ 5 ms 未満と、リスクチェックのレイテンシ 1 ms 未満だ。どちらもキー入力から回線までの数字ではない。だから、どのベンダーに対してもそうするように、両方について計測ポイントと負荷を確かめること。
amBrain は Spectre Trade のトレーディングターミナルを構築した。amBrain は MOEX のコロケーションで本番稼働するミニ取引所も構築している。この記事の設計は一般的なものである。どちらのシステムを説明するものでもなく、いずれかが使っているプロトコルの名前も挙げていない。
三つの形態:フルデリバリー、専任チーム、あるいはあなたのチームに入るエンジニア。顧客は、プロダクトとコードの完全な所有権を保持する。ただし、私たちの再利用可能なコンポーネントは除く。
amBrain を含め、どのベンダーとの最初の打ち合わせの前にも、利用する取引所、それぞれが使う FIX のバージョンまたは方言、そして明示した計測ポイント間で必要なレイテンシを書き出しておくこと。
現在のアーキテクチャと気になっている障害シナリオをお持ちください。30 分で一緒に確認します。