暗号資産取引所のマッチングエンジンは実際どう動いているのか
テクノロジー 取引エンジン アーキテクチャ

暗号資産取引所のマッチングエンジンは実際どう動いているのか

C
Codono Team
| · Updated March 10, 2026 | 2 min read

目次

取引所の命運を握るソフトウェア

取引所の創業者は誰もがUIの話をしたがります。洗練されたTradingViewチャート、ダークモードの切り替え、モバイルアプリ。もちろん、それらはユーザー獲得にとって重要です。しかし、取引所が最初の本格的な取引日を生き抜けるかどうかを実際に決めるものを知りたいなら、マッチングエンジンを見てください。

マッチングエンジンは、入ってくる買い注文と売り注文を受け取り、どの注文同士を約定できるかを判断し、取引を執行する中核ソフトウェアです。簡単に聞こえますが、実際は違います。設計の悪いマッチングエンジンは、負荷時に注文を黙って取りこぼし、幽霊のような約定を生み出し、不正確な残高を作り、監査人が匙を投げるような会計上の悪夢を生じさせます。私はこれらを十分にデバッグしてきたので、その苦しみは身に染みています。

人々が驚くのは、コアロジックがいかに見かけほど大きくないかということです。既存の売り注文に対して買い注文をマッチングさせる基本アルゴリズムは、100行以下のコードで書けます。しかし、そのおもちゃの実装と本番グレードの取引エンジンの差は、約50,000行に及ぶエッジケース処理、永続化ロジック、リカバリ機構、パフォーマンス最適化です。

最新のマッチングエンジンの内部で実際に何が起きているのか、そしてなぜ各設計判断が重要なのかを順に見ていきましょう。

マッチングエンジンが実際に行うこと

教科書的な定義はひとまず忘れてください。マッチングエンジンが実際に行っていること、それは取引日の毎ミリ秒ごとに次のような処理です。

  1. 注文の受付 — タイプ(指値、成行、ストップ)、価格(場合による)、数量、トレーダーIDを持つ買いまたは売りのリクエスト。
  2. 注文の検証 — 価格がティックサイズの要件を満たしているか、数量が最小ロットサイズを満たしているか、トレーダーに十分な残高があるか、注文が取引所ルールに違反していないかを確認。
  3. マッチングの試行 — オーダーブックの反対側をスキャンし、マッチ可能な待機注文を探す。$50,000の買いは、$50,000以下のあらゆる売りとマッチできます。
  4. 取引の執行 — 各マッチについて、取引レコードを作成し、両トレーダーの残高を更新し、オーダーブックを調整。
  5. 残りの処理 — 注文が完全に約定しなかった場合、オーダーブックに残る(指値注文)か、キャンセルされる(残りの流動性がない成行注文)。
  6. イベントの発行 — 取引執行、オーダーブック更新、残高変更をシステムの他の部分へブロードキャスト。

ステップ1から6はアトミックに実行される必要があります。「結果整合性」でも「後で突合する」でもありません。アトミックに。ステップ4が成功してステップ6が失敗すれば、トレーダーが決して目にしないサイレントな約定が発生します。ステップ3が成功してステップ4が部分的に失敗すれば、板の上に幽霊の流動性が残ります。どちらの状況も、どんなハッキングよりも早く信頼を破壊します。

これが、マッチングエンジンが特定の取引ペアに対してほぼ常にシングルスレッドの逐次プロセッサである理由です。ここでの並行処理は味方ではなく、負債です。詳しくはスケーリングの話で触れます。

オーダーブックのデータ構造:パフォーマンスの成否を分ける部分

オーダーブックは、待機中のすべての指値注文を価格レベルごとに整理して保持するデータ構造です。2つのサイドがあります。ビッド(買い注文)とアスク(売り注文)です。ビッドは高い順に、アスクは安い順にソートされます。ベストビッドとベストアスク、つまり各サイドの最上位の価格がスプレッドを定義します。

これに適したデータ構造の選択は、あなたが下す最も重要なアーキテクチャ上の決定のひとつです。現実の選択肢は次のとおりです。

ソート済み配列または連結リスト

最もシンプルなアプローチ。価格レベルのソート済みリストを維持し、各レベルに注文のキューを持たせます。

長所: 実装が極めて簡単。キャッシュフレンドリーなメモリレイアウト。板を走査する際のイテレーションが速い。

短所: 挿入はO(n)(nは価格レベル数)。BTC/USDTのように数千のアクティブな価格レベルがあるペアでは遅くなります。シフトが必要なため削除もO(n)。

結論: プロトタイプには十分。本番の本格的なボリュームには受け入れられない。

平衡二分探索木(赤黒木、AVL木)

ほとんどの本番マッチングエンジンが使っているものです。自己平衡BSTは挿入、削除、検索にO(log n)を提供します。最小ノードと最大ノードへのポインタを維持すれば、ベストビッドとベストアスクも効率的に見つけられます。

長所: すべての重要操作がO(log n)。十分に理解されたアルゴリズム。ベストビッドとベストアスクのポインタ管理が容易。

短所: ポインタ主体の構造はキャッシュミスを引き起こす可能性がある。リバランス時の木の回転が定数倍のオーバーヘッドを追加する。

結論: 業界標準には十分な理由がある。特別な要件がない限り、これを使うべきです。

ハッシュマップとスキップリストの組み合わせ

一部の高頻度取引会社は、価格レベルをキーとするハッシュマップと、順序付けのためのスキップリスト(または類似構造)を組み合わせて使っています。これにより、特定の価格レベルへのO(1)ルックアップと、順序付き走査へのO(log n)が得られます。

長所: 既存の価格レベルに注文を追加する一般的なケースで驚異的に速い。

短所: 正しく実装するのがより複雑。スキップリスト部分は新規価格レベルの挿入に依然としてO(log n)が必要。

結論: プロファイリングの結果、ほとんどの注文が既存の価格レベルに乗ることが示されるなら検討の価値あり(実際、取引量の多いペアではこれが真実です)。

現実世界のハイブリッド

本格的な実装の多くが実際にどうなっているかを紹介します。価格レベルのインデックスに平衡BSTを使い、各価格レベルは個別注文の双方向連結リスト(FIFOキュー)を保持します。さらに、注文IDから注文ノードへのハッシュマップを維持するため、キャンセルはO(1)のルックアップと連結リストからのO(1)の削除で済みます。

このキャンセル用ハッシュマップは非常に重要です。アクティブな取引所では、キャンセル量は通常、取引執行量の10〜50倍です。マーケットメーカーは絶えず注文を出してはキャンセルしています。キャンセルの経路が遅ければ、エンジン全体が停滞します。

価格時間優先:公平性の契約

価格時間優先(FIFOマッチングとも呼ばれる)は、実質的にすべての正当な取引所で使われている標準アルゴリズムです。ルールはシンプルです。

  1. 注文はまず価格で優先順位付けされる。$50,001の買い注文は$50,000の買いより先に約定する。
  2. 同じ価格レベルでは、注文は時間で優先順位付けされる。先に到着した注文が先に約定する。

当然のように聞こえますが、これには深遠な意味があります。価格時間優先は根本的に公平性の保証です。ある価格で先に注文を出したなら、後から同じ価格を出してキューに割り込む者はいない、ということです。キューにおけるあなたの位置はあなたの財産です。

なぜこれがそれほど重要なのでしょうか。厳密な価格時間優先がなければ、一連の操作的な行為への扉を開くことになるからです。取引所の運営者は理論上、特定のマーケットメーカーを優遇するためにキューを並べ替えられます。接続の速いトレーダーは注文をキャンセルして再発注し、前に割り込めます。これらは仮定の話ではありません。怪しい取引所で実際に起きたことであり、規制当局がマッチングエンジンの公平性を気にする理由そのものです。

一部の取引所は代替の優先順位スキームを試してきました。プロラタマッチング(一部の先物市場で使用)では、ある価格レベルでの約定がすべての待機注文に比例的に分配されます。また、サイズ時間優先では大口注文が優先されます。しかし、標準的な現物取引所では価格時間FIFOが標準であり、それから逸脱するには非常に正当な理由とトレーダーへの明確な開示が必要です。

実装上、人々がつまずく細部はタイムスタンプの分解能です。クロックの分解能がミリ秒しかなければ、同じミリ秒内に到着した2つの注文は任意の順序になります。本番エンジンはマイクロ秒またはナノ秒のタイムスタンプを使います。そしてタイムスタンプは、注文がAPIゲートウェイに到達した時点ではなく、マッチングエンジンの処理キューに入った瞬間に付与される必要があります。

レイテンシとスループット:「速い」の本当の意味

マッチングエンジンのパフォーマンス数字は文脈なしに飛び交っているので、実際のベンチマークを示しましょう。

Tier 1取引所(Binance、Coinbase、Kraken): これらのエンジンは個々の注文を一桁マイクロ秒で処理します。公表されている数字は通常、取引ペアあたり毎秒100,000件以上の注文、マッチングレイテンシ5マイクロ秒未満を謳っています。このレベルではC++やRustで書き、ロックフリーのデータ構造を使い、スレッドをCPUコアにピン留めし、カーネルのネットワークスタックをバイパスします。

Tier 2取引所(中規模、確立済み): 注文処理は50〜500マイクロ秒の範囲。スループットは毎秒10,000〜50,000件の注文。通常はJava、Go、C++で書かれています。正当な取引所の大多数がこの領域で運営されており、正直なところ、ほとんどのユースケースには十分すぎる性能です。

Tier 3取引所(スタートアップ、小規模プラットフォーム): 処理は1〜10ミリ秒の範囲。スループットは毎秒1,000〜10,000件の注文。多くはPython、PHP、Node.js、Javaで書かれています。1日の取引高が1,000万ドル未満の取引所にはまったく十分です。

誰も口に出したがらないことがあります。新規取引所の95%にとって、Tier 3のパフォーマンスで完全に十分だということです。あなたの取引所が1日1,000件の取引を処理する場合、これは非常に健全なローンチですが、必要な平均スループットは約0.01注文/秒です。平均の100倍のピークバーストを考慮しても、必要なのはせいぜい1注文/秒程度です。シングルコアで動くPython製マッチングエンジンでも、余裕で処理できます。

パフォーマンスの問題はローンチ日のことではありません。成長したときに何が起きるかです。あなたのエンジンは、全面的な書き直しなしに毎秒1,000件から100,000件へスケールできますか。それこそが本当に重要なアーキテクチャの問いです。

これが、実績のある取引所ソフトウェアを選ぶことが重要な理由の大きな部分を占めています。Codonoの暗号資産取引所プラットフォームには、すでに本番規模で負荷テスト済みのマッチングエンジンが搭載されているため、自前の実装が最初のトラフィックスパイクを生き抜けるかどうかに賭ける必要はありません。しかも取引所スクリプトは完全に非暗号化なので、チームがマッチングロジックを直接レビューし、チューニングできます。

注文タイプ:見た目以上に複雑

指値注文と成行注文は単純です。しかしストップ注文を追加した瞬間に事態は面白くなり、OCO(one-cancels-other)注文を追加すると、状態管理の複雑さはほぼ倍増します。

指値注文

基本中の基本。「1 BTCを$49,500以下で買う」。注文は約定、キャンセル、または失効するまで板に残ります。実装は単純で、検証し、反対側とのマッチングを試み、約定しなかった数量を板に残します。

成行注文

「現在の価格がいくらでも1 BTCを買う」。注文は板の反対側を食い進み、完全に約定するか流動性がなくなるまで価格レベルを消費していきます。重要な実装の詳細は、価格保護メカニズムが必要なことです。薄い板での成行買いが、誰かが冗談で置いた売り注文のせいで$999,999で約定してはいけません。ほとんどのエンジンは、最大スリッページパラメータか、直近の取引価格からの乖離率に基づく暗黙の指値価格を実装しています。

ストップロス注文とストップリミット注文

ここでマッチングエンジンは本当に厄介になります。ストップ注文は条件付き注文です。「市場価格が$48,000に達したら、成行売り注文を発注する」。ストップ注文自体は可視のオーダーブックには載りません。別のデータ構造、いわゆるストップブックに置かれ、ストップ価格以上(以下)での取引執行によってトリガーされます。

厄介なのはストップの連鎖です。$48,000での取引がストップ売りをトリガーし、そのストップ売りの執行が価格を$47,500まで押し下げ、さらに多くのストップがトリガーされ、価格がさらに下がるという連鎖が、ミリ秒単位でオーダーブックを枯渇させることがあります。歴史上のいくつかのフラッシュクラッシュで実際に起きたことがこれです。エンジンにはサーキットブレーカーが必要です。時間枠あたりの最大価格変動、オーダーブックの最小深度チェック、そして異常時にマッチングを一時停止する機能です。

OCO(one-cancels-other)注文

OCOは2つの注文をリンクします。典型的には利確の指値注文とストップロスです。どちらか一方が約定すると、もう一方は自動的にキャンセルされます。これには注文間の関係グラフの維持が必要で、キャンセルは約定とアトミックに行われなければなりません。ストップロスがトリガーされて約定したのに、利確のキャンセルが数ミリ秒でも遅れれば、両方の注文が約定し、トレーダーに意図しないポジションを与えてしまいます。

Codonoのエンジンはこれらの高度な注文タイプをネイティブに処理し、先物取引の注文タイプであるreduce-onlyやpost-onlyなど、さらに別の複雑な層を追加する注文もサポートしています。

取引所を破壊するエッジケース

このセクションこそ、マッチングエンジンを実際に出荷したエンジニアと、本で読んだだけの人を分ける部分です。実際の本番インシデントを引き起こしたエッジケースを紹介します。

自己売買防止(STP)

トレーダーが$50,000の待機売り注文を持っていて、$50,000の買い注文を発注したらどうなるでしょうか。STPがなければ、トレーダーは自分自身と取引し、経済的意味のない両側の手数料を支払います。マーケットメーカーは、複数の戦略を同時に走らせているときに、これを頻繁に誤ってやってしまいます。

STPポリシーが必要です。一般的な選択肢は3つです。

  • 新しい注文をキャンセル: 自己売買になる新規注文がキャンセルされる。
  • 古い注文をキャンセル: 待機中の注文がキャンセルされ、新規注文はマッチングを継続する。
  • 両方をキャンセル: 両方の注文がキャンセルされる。

ほとんどの取引所はデフォルトで新しい注文のキャンセルにしていますが、トレーダーごとに設定可能にすべきです。マーケットメーカーはこの点に強いこだわりを持っています。

ダスト注文

0.00000001 BTCの注文をどうしますか。あるいは、約定の結果0.000000003 BTCの端数が残ったら。これらのダスト金額は取引するには小さすぎ、出金するにも小さすぎますが、オーダーブックとデータベースを詰まらせます。

最小注文数量、最小ノショナル金額(価格×数量がある閾値、通常数ドルを超える必要がある)、そして最小未満の残高を定期的に掃き集めるダスト回収メカニズムが必要です。

ティックサイズとロットサイズの強制

価格はティックサイズの倍数(例:BTC/USDTなら$0.01)でなければなりません。数量はロットサイズの倍数(例:0.00001 BTC)でなければなりません。これをマッチングエンジンのレベルで強制しなければ、$50,000.003のような他のどの注文とも一致しない価格の注文が発生し、永遠に板に残ります。さらに悪いことに、残高の不一致を引き起こす小数精度の問題が発生します。

オーバーフローと精度

これは他のどれよりも多くの取引所を痛い目に遭わせてきました。価格と数量に浮動小数点演算を使っているなら、やめてください。今すぐに。浮動小数点演算は丸め誤差を生み、それが数百万件の取引を通じて複利で積み上がり、実際の残高不一致になります。本番マッチングエンジンは、固定小数点整数演算($50,000.00を整数5000000として表現)か、任意精度の小数ライブラリのどちらかを使わなければなりません。第三の選択肢はありません。

マッチング後の残高チェック

取引前の残高検証があっても、取引後の残高アサーションが必要です。すべての取引執行後に、全ユーザー残高と取引所手数料の合計が期待される総額と一致することを検証します。この不変条件が壊れたら、マッチングを停止して調査します。これは、そうでなければユーザー資金をゆっくりと流出させるバグに対する最後の防衛線です。

スケーリング戦略:シングルスレッドのジレンマ

マッチングエンジンは取引ペアごとにほぼ常にシングルスレッドだと言ったのを覚えていますか。これは明らかなスケーリング上の課題を生みます。最新ハードウェア上のシングルスレッドが処理できるのは、単純な操作で毎秒およそ100,000〜500,000件です。ほとんどの取引所にはそれで十分です。しかし、十分でない場合はどうするでしょうか。

垂直スケーリング

より速いハードウェアを投入します。より高いクロック速度のCPU、より多くのL3キャッシュ、より速いメモリ。これは最初に試すべきことで、多くの場合十分です。最新の高頻度取引エンジンは、基本的なマッチング処理でCPUを完全にバイパスするFPGAベースのネットワークカードを備えたカスタムハードウェア上で動いています。しかし一般的な取引所なら、5GHz超のプロセッサと128GBのRAMを備えた高性能サーバーで、膨大な量を処理できます。

取引ペアごとの水平スケーリング

最もシンプルな水平スケーリング戦略は、取引ペアごとに1つのマッチングエンジンインスタンスを走らせることです。BTC/USDTには専用のエンジン、ETH/USDTにも専用のエンジン。それらは完全に独立しており、共有状態も調整も不要です。これは取引ペア数に対して線形にスケールします。

課題は残高管理です。トレーダーが10 BTCを持ち、5つのBTC取引ペアに注文を出す場合、各マッチングエンジンは利用可能残高を知る必要があります。標準的なアプローチは、各エンジンが注文を受け付ける前に確認する中央集権的な残高サービスです。この残高サービスが新しいボトルネックになりますが、複雑なマッチングロジックではなく単純な読み書き処理を行うだけなので、スケールははるかに簡単です。

取引ペア内のシャーディング

最高レベルのボリュームを持つペアでは、オーダーブック自体のシャーディングが必要になるかもしれません。ひとつのアプローチは価格帯でのシャーディングで、あるエンジンが$49,000〜$50,000の価格を処理し、別のエンジンが$50,000〜$51,000を処理します。しかしクロスシャードマッチング(価格帯をまたぐ成行注文)は恐ろしく複雑です。

正直に言うと、Binanceレベルのボリュームを処理していない限り、これは必要ありません。そしてBinanceレベルのボリュームを処理しているなら、先に取り組むべきもっと大きなアーキテクチャ上の懸念があるはずです。

ほとんどの取引所運営者にとって賢い選択は、単一ペアのマッチングエンジンをシャーディングしようとするよりも、流動性アグリゲーションでオーダーブックの深度を補強することです。

メモリ対ディスク:永続化の問題

マッチングエンジンのオーダーブックはメモリ上に存在します。そうあるべきものです。ディスクI/Oは、リアルタイムマッチングにはまったく受け入れられないミリ秒単位のレイテンシを追加します。しかしエンジンがクラッシュしたらどうなるでしょうか。待機中のすべての注文を失うわけにはいきません。

標準的なアーキテクチャは3つの層を使います。

レイヤー1:インメモリオーダーブック。 これがホットパスです。すべてのマッチングはここで行われます。通常動作中のディスクI/Oはゼロです。

レイヤー2:先行書き込みログ(WAL)。 すべての受注とすべてのマッチングイベントは、エンジンが処理する前にディスク上の逐次ログに追記されます。エンジンがクラッシュしたら、最後のチェックポイントからログをリプレイしてオーダーブックを再構築します。逐次書き込みは高速で、NVMeドライブは毎秒500,000件以上の逐次書き込みを持続でき、十分すぎる性能です。

レイヤー3:定期的なスナップショット。 N秒ごと(またはNイベントごと)に、エンジンはオーダーブックの完全なスナップショットをディスクに書き込みます。これにより、クラッシュ後にWALをどこまで遡ってリプレイする必要があるかが制限されます。スナップショットがなければ、24時間稼働後のクラッシュで数百万のイベントをリプレイする必要が出てきます。

WALが重要な部分です。レイテンシを犠牲にせずに耐久性を得られます。トレードオフは、ディスクへの書き込みが非同期になることです。メモリ内で取引がマッチしてからディスクに永続化されるまでの間に、ごくわずかな(マイクロ秒の)時間窓があります。そのちょうどその窓の中でマシンが電源を失えば、それらのイベントを失います。ほとんどの取引所にとって、このリスクは許容範囲です。絶対的なゼロロス保証が必要な場合は、取引を確認応答する前にスタンバイマシンへの同期レプリケーションを追加します。

Codonoの対処方法

マッチングエンジンをゼロから構築するということは、上で説明したすべての問題を解決することを意味します。データ構造、優先順位ロジック、エッジケース、永続化、スケーリング、そのすべてを。そして市場は進化し新しい注文タイプが登場するため、それを永遠にメンテナンスし続けることになります。

これこそが、私たちがCodonoの取引エンジンをこのように作った理由です。Codono取引所ソフトウェアには、以下を処理する本番グレードのマッチングエンジンが含まれています。

  • マイクロ秒のタイムスタンプ分解能を持つ価格時間優先FIFOマッチング
  • 指値、成行、ストップロス、ストップリミット、OCOを含むすべての標準注文タイプ
  • APIキーごとに設定可能なポリシーを持つ自己売買防止
  • 取引パイプライン全体にわたる固定小数点演算 — 残高計算の近くに浮動小数点は一切なし
  • 自動チェックポイントとリカバリを備えた先行書き込みログ
  • 取引ペアごとの独立したエンジンインスタンスによる水平スケーリング
  • フラッシュクラッシュ保護のための組み込みサーキットブレーカー

このエンジンは私たちの流動性エンジンと直接統合されているため、オーガニックなオーダーブックが薄くても、入ってくる注文は集約された外部流動性とマッチできます。これは、オーガニックな流動性の構築に時間がかかる新規取引所にとって特に重要です。

プログラムによるアクセスが必要な運営者のために、APIレイヤーはオーダーブック更新と取引執行レポートのための低レイテンシWebSocketフィードを提供し、マーケットメーカーが効率的にエンジンとやり取りできます。

まとめ

マッチングエンジンは概念としては見かけよりも単純で、実行においては残酷なほど困難です。コアアルゴリズムは頭に収まります。しかし本番上の懸念、すなわち永続化、リカバリ、公平性、精度、エッジケース、負荷時のパフォーマンスは、何年分ものエンジニアリング努力に相当します。

私の正直なアドバイスはこうです。マッチングエンジン開発があなたの中核的な強みであり競争優位性でない限り、ゼロから構築しないでください。実戦で鍛えられたソフトウェアを使い、エンジニアリングリソースを取引所を実際に差別化するもの、つまりユーザーエクスペリエンス、コインの上場、規制コンプライアンス、マーケティングに集中させてください。マッチングエンジンは、デプロイするだけの解決済みの問題であるべきであり、あなたのランウェイを食い潰す科学プロジェクトであるべきではありません。

成功する取引所は、最も派手なマッチングエンジンを持つ取引所ではありません。賢いビルドかバイかの判断を下し、迅速にローンチし、ユーザーにとって重要なことを改善し続けた取引所です。あなたのマッチングエンジンは、正確で、十分に速く、信頼できる必要があります。芸術作品である必要はありません。動けばいいのです。


Codonoのマッチングエンジンは、価格時間優先、組み込みサーキットブレーカー、流動性アグリゲーションにより、毎秒数千件の注文を処理します。現物取引所の機能ページをご覧いただくか、デモをリクエストして実際にお試しください。

テクノロジー 取引エンジン アーキテクチャ インフラ
C

Codono Team

Codono builds enterprise-grade crypto exchange software deployed by 250+ operators across 40+ countries. Our team writes from production experience running spot, derivatives, custody, and compliance at scale.

View all posts by Codono Team →

Build Your Exchange with Codono

Complete crypto exchange software with spot, futures, P2P, and 15+ blockchains.