本稿では暗号資産市場におけるトライアングルアービトラージ(三角裁定)を、概念から具体的な実行手順、数式、失敗する典型パターン、実務の運用設計まで一貫して解説します。価格の歪みは短時間で消えるため、チャンスは秒単位で出現・消滅します。重要なのは「何を、どの順番で、どの条件なら回すか」を機械的に決めることです。
1. 何をもってトライアングルとするか
三角裁定とは、同一取引所内で 3通貨・3ペア を経由して原資通貨に戻すラウンドトリップで、理論価格との差(エッジ)を瞬時に刈り取る戦略です。例として、原資をUSDTとし、次の3ペアで回します。
例:USDT→BTC(ペア:BTC/USDTの買い)→ETH(ペア:ETH/BTCの買い)→USDT(ペア:ETH/USDTの売り)
この一周でUSDTが増えれば成功です。三角裁定は大きく2タイプに分かれます。
- 所内三角(Intra-Exchange Triangular):同一CEX内で3ペアを同時/連続執行。送金なし。レイテンシ最小。
- 所間三角(Inter-Exchange Triangular):A所・B所・C所の価格差を三角で回す。送金や建玉持越しが絡むため、難易度・コスト・リスクは大幅に上昇。
初心者はまず「所内三角」から始めるのが合理的です。板厚・手数料・最小数量・約定方式(FOK/IOC/POST-ONLY)など、取引所仕様差で結果が大きく変わります。
2. 価格・数量・費用の表記と基本式
以下の記号を使います。原資はU(USDT)とします。
- ペア1:BTC/USDT の買い。価格
P1 = Ask(BTC/USDT)
、手数料率f1
、希望数量q_btc
。 - ペア2:ETH/BTC の買い。価格
P2 = Ask(ETH/BTC)
、手数料率f2
、得られるq_eth
。 - ペア3:ETH/USDT の売り。価格
P3 = Bid(ETH/USDT)
、手数料率f3
。
このとき、投入U(USDT)を U_in
とし、Maker/Taker手数料・スリッページ・価格インパクトを含む実行後の戻りU(USDT)期待値 U_out
は、概ね次式で近似します。
q_btc = (U_in / P1) * (1 - f1) * (1 - s1)
q_eth = (q_btc / P2) * (1 - f2) * (1 - s2)
U_out = (q_eth * P3) * (1 - f3) * (1 - s3)
Expected Edge (gross) = (U_out - U_in) / U_in
ここで s1, s2, s3
は各レグのスリッページ・価格インパクトの実効割引係数(0〜数%程度)です。
意思決定条件の一例は、
条件: Edge >= FEE_ALL + SLIPPAGE_ALL + BUFFER
BUFFER = 運用者が設定する安全マージン(例: 0.10%)
さらに最小発注数量・ロット刻み・最小オーダー名目金額を満たすようクリッピングします。約定方式は IOCまたはFOK を基準とし、POST-ONLY(メイカー限定)はレイテンシの観点で不利になりやすい点に注意します。
3. 具体例:数値で回す
例として以下の板条件とします(手数料は全てテイカー、スリッページは板厚から推定)。
- P1 = 65,000.00 USDT/BTC、f1 = 0.05%、s1 = 0.03%
- P2 = 18.5000 mBTC/ETH(= 0.0185 BTC/ETH)、f2 = 0.05%、s2 = 0.04%
- P3 = 3,600.00 USDT/ETH、f3 = 0.05%、s3 = 0.03%
- 投入 U_in = 10,000 USDT
q_btc = (10,000 / 65,000) * (1 - 0.0005) * (1 - 0.0003)
≈ 0.15380 BTC
q_eth = (0.15380 / 0.0185) * (1 - 0.0005) * (1 - 0.0004)
≈ 8.302 ETH
U_out = 8.302 * 3,600 * (1 - 0.0005) * (1 - 0.0003)
≈ 29,859.5 USDT
一見、大きく増えていますが、これはP2・P3の単位をmBTCやETHで取り違えると起きがちな「桁ミス」です。実務ではすべての通貨とペアの 価格単位を統一 し、換算を厳密に行います。正しくは:
- P2が「ETH/BTC = 0.0185」の場合、
q_eth = q_btc / 0.0185
はOK。 - P3が「ETH/USDT = 3,600」の場合、
U_out = q_eth * 3,600
はOK。
上の試算は桁の辻褄は合っていますが、実市場では 3レグの同時約定保証はない ため、部分約定・価格飛び の可能性を組み込みます。バックテスト時は、
- 各レグの 実効価格 = 気配最良±Xティック(板厚依存)
- ロット分割(例:原資を5分割し、IOC連打)
- 時間制約(TTL 250ms、1秒で未完了なら全撤退)
などの 保守的な約定モデル を使うと、実運用に近い期待値を得られます。
4. どこにエッジが生まれるか
三角裁定の源泉は、板間の反応速度差 と ペア間のアービトラージ制約 です。具体的には、
- USD基軸 vs BTC基軸の更新遅延:BTC/USDTの変化がETH/BTCに伝わるまでの数百msのラグ。
- 四捨五入・ロット刻み・最小名目金額:端数が残り、理論裁定が打てない「摩擦」部分に微小エッジが残る。
- メイカー/テイカー手数料差:メイカー割引を絡めると、理論上負のエッジが正に転ぶことがある。
- 内部流動性の偏り:ETH/USDTは厚いがETH/BTCが薄い、など。
5. 実務フロー:準備→検出→執行→回収
5.1 準備
- 取引所API鍵を発行(読み取り+取引、出金は無効で開始)。
- 手数料率(VIP/メイカー/テイカー)、最小ロット、最小名目、価格刻み、注文タイプ(FOK/IOC/TIF)を仕様書から取得し、ローカルに固定値として保持。
- 原資はUSDTに統一。BTC・ETHは在庫0で開始(在庫バイアスを避ける)。
- 時刻同期(NTP)。100ms単位で誤差が出る環境は避ける。
5.2 検出
3ペアの最良気配と板厚を50〜100msでポーリングまたはストリーム購読し、上記の Expected Edge
を算出。下限閾値 THRESH
を超えた瞬間に、同時3レグIOC を構築します。
if Edge >= THRESH and size_ok and risk_ok:
place IOC: Buy BTC/USDT, Buy ETH/BTC, Sell ETH/USDT
else:
pass
size_ok は各板の10〜20ティック合算の数量が投入量を余裕で満たすこと、risk_ok は連続失敗回数・滑り過多・APIエラー率などのヘルス指標が許容内であることを意味します。
5.3 執行
- 3レグ同時発注(非同期)。最初に約定率が高いETH/USDT(売り)を先行させる構成も検討。
- 部分約定が出たら、残り2レグを同量で即キャンセル/再送 し、バランスを維持。
- 1レグでも未約定が残る場合はハッジ注文(例:先物の逆方向少量)で露出を最小化。
5.4 回収と在庫ゼロ化
一周後、USDT残高が増えていれば成功。万が一、中間通貨の在庫が残った場合は、即時の反対売買でフラット化(在庫を翌日に持ち越さない)。
6. コストの完全内訳
- 取引手数料:メイカー/テイカー、VIP段位、支払トークン割引(例:BNB払い)を反映。
- スリッページ:板厚から数量に応じた実効価格を推定。過去の約定履歴から回帰モデルを作ると精度が上がる。
- 資本コスト:先物ヘッジを絡めると資金調達/ファンディング支払いが発生。
- 失敗コスト:1レグのみ約定時の即時反対売買コスト(スプレッド×2+手数料)。
- インフラコスト:低レイテンシ回線・VPS費用。
7. 成功/失敗の判断ロジック
以下のような リアルタイムKPI をダッシュボード化し、閾値で自動停止させます。
- Edge観測分布(p50/p90/p99)
- 実行成功率(同時3レグ完遂率)と平均滑り
- 純利益/日、純利益/投入USDT(資本回転効率)
- 連続失敗回数・APIエラー率
停止条件例:連続3回失敗 or 平均滑り>=0.12% or APIエラー率>=1%。
8. 典型的な落とし穴
- 片寄り在庫の放置:ETHだけ余る、BTCだけ不足する。ハッジで即フラット化。
- 単位取り違い:mBTCや価格表記の左右(BASE/QUOTE)で計算が崩れる。
- 手数料設定の誤り:メイカー前提で計算し、IOC実行で実費が増える。
- 小数刻み:price_tick と qty_step に丸め忘れ。発注拒否や意図せぬサイズ縮小。
- レイテンシ:ローカル/クラウドの地理距離で200〜400ms遅れる。
9. 検証(バックテスト)と前向きシミュレーション
板スナップショット(L2)を100ms刻みで収集し、保守的な約定モデルで再現します。最低でも以下を組み込みます。
- 各レグのIOCヒット率を板厚から確率化
- 約定遅延を正規分布(例:μ=120ms, σ=40ms)でサンプル
- 価格飛びのジャンプ過程(ポアソン+ジャンプ幅分布)
前向きシミュレーションでは、誤検出率(False Positive) を最小化する閾値最適化(ROCカーブ)を行い、最大ドローダウンを最小化する発注分割数と同時系数を決定します。
10. 実装スケッチ(疑似コード)
// 価格更新イベントで呼ばれる
onTick():
snapshot = getBestQuotes(["BTC/USDT","ETH/BTC","ETH/USDT"])
edge = calcEdge(snapshot, fee, slip_model)
if edge >= THRESH and size_ok(snapshot) and health_ok():
orders = [
IOC("BUY", "BTC/USDT", size_btc(snapshot)),
IOC("BUY", "ETH/BTC", size_eth(snapshot)),
IOC("SELL", "ETH/USDT", size_eth(snapshot))
]
result = sendConcurrent(orders, ttl=250ms)
if not result.allFilled:
hedgeResidual(result) // 露出中立化
recordFail(result)
else:
recordSuccess(result)
11. 先物・パーペチュアルを絡める応用
三角のどこか1レグをパーペチュアルで代替し、資本効率(証拠金レバレッジ)を高める設計もあります。この場合、ファンディングレートがコストに追加されるため、Edge - Funding - Fee - Slip
が正である時間帯に限定するフィルタが必須です。資金調達コストが急変するイベント(雇用統計、FOMC、半減期前後など)は原則停止します。
12. 資金管理・損失限定
- 1回あたり投入上限:口座残高の1〜5%
- 連続失敗で指数的にサイズを縮小(1.0→0.7→0.5→停止)
- 日次損失限度額(例:-0.8% of NAV)に達したら当日停止
- 週次でKPIレビューし、THRESHや分割数をチューニング
13. 所間三角に進む際の追加論点
- 入出金手数料・チェーン詰まり(ブロック混雑)・着金遅延
- KYC段位差・限度額・地域制限(銘柄取扱差)
- 価格転送の遅延を跨いだ在庫持越しリスク
所間は一撃の粗利は大きくなり得ますが、在庫・送金・法規制の3点で難易度が跳ね上がります。まずは所内で堅牢な基盤を作り、十分な統計とプレイブックを得てから段階的に拡張するのが堅実です。
14. まとめ:勝ち筋のチェックリスト
- 単位系・刻み・最小名目を厳密管理
- Edge >= すべてのコスト+安全マージン
- IOC同時3レグ、部分約定時の残差ハッジを自動化
- 失敗コストを「設計時点」で見積もり、停止条件を先に決める
- 実データで保守的バックテスト→前向き検証→小規模運用→拡張の順
三角裁定は「難しそう」に見えて、実は 設計と規律 のゲームです。機械的ルールと保守的な前提を貫けば、相場観に依存しない一貫性のあるリターン源泉になり得ます。
コメント