レイヤー2ブリッジレイテンシーアービトラージ:初心者向けプレイブック(MQL4 EA付き)

システムトレード

本記事では、同一アセット(例:ETH)を複数のLayer‑2(Arbitrum、Optimism、Baseなど)にまたいで保有し、ブリッジ(橋渡し)に伴う伝播遅延・流動性偏在・手数料構造の違いから短時間に発生する価格乖離を狙う裁定手法を、初心者向けにゼロから解説します。中央集権取引所間アービトラージの考え方と共通点は多い一方で、オンチェーン特有の手数料、最終性、MEV、ブリッジ設計差、リレー遅延が絡む点が大きく異なります。ここを正しく理解し、負けにくい土俵を作ることが目的です。

戦略の全体像

同一アセットの価格は理論上どのチェーンでも一致すべきですが、現実には以下の複合要因で短時間の乖離が発生します。

  • ブリッジの確定遅延(メッセージの最終性まで数分〜数十分)
  • DEX毎のプール規模・価格アルゴリズム差(UniV2/V3/その他)
  • 流動性の時間帯偏在(欧米/アジア時間、イベント直後)
  • ガス価格の急変、サンドウィッチ/MEVなど実効コストのブレ
  • 中央集権取引所(CEX)価格への追随速度差

コアの考え方は簡単です。割高チェーンで売り、割安チェーンで同量を買う。その後、価格が収斂するか、ブリッジでポジションを同一チェーンに寄せてクローズします。常に両建て・ネットフラットにすることで方向リスクを抑制し、乖離の解消分だけを取りに行きます。

準備(ウォレット/ネットワーク/資金配分)

  1. ウォレット:メジャーなL2(例:Arbitrum/Optimism/Base)に接続できるウォレットを用意します。各L2で少額のネイティブガス(ETH等)を常備してください。
  2. 資金配分:裁定は同時両建てが基本です。各L2に同額価値の基準アセット(ETHやUSDC等)をあらかじめ配分し、瞬時に両側で約定できるようにします。
  3. DEX口座:主要DEXでの許可(Approval)を前もって済ませ、初回の承認トランザクション遅延をなくします。
  4. 価格取得:同一アセットのマルチチェーン価格と手数料見積りを同時に見られる画面(自作でも可)を用意します。
  5. 記録用シート:実行時間、チェーン、トランザクションハッシュ、数量、コスト、理論スプレッド、実現損益(PnL)を記録するテンプレートを作ります。

実運用フロー(手順)

  1. モニタリング:対象アセット(例:ETH)の価格を各L2/DEXで同時監視します。ここで重要なのは実効価格(価格 × 数量に対するスリッページとガス・MEVを含む)です。
  2. トリガー検出:実効価格差が事前に決めた閾値(例:0.25%)を上回ったらアラート。
  3. 同時約定:割高チェーンで売り、割安チェーンで買う。数量は両側同量。価格差の計測ベースと同じDEX/プールを使うこと。
  4. 収斂待ち or ブリッジ:短時間で収斂しなければ、手数料・最終性・時間を天秤にかけて、ポジションをどちらかへブリッジしてクローズ。
  5. 記録と検証:実行後は記録を即時更新し、理論スプレッド − 総コストが十分にプラスだったかを検証します。

価格差の測り方と基準線

乖離の判定は実効価格の比較で行います。基準式は次の通りです。

EffectivePrice = FillPrice × (1 ± Slippage) ± GasCostPerUnit ± MEVCostPerUnit

両チェーンの実効価格差を Spread = EffectivePrice_L2A − EffectivePrice_L2B と定義し、

Edge = |Spread| − (BridgeFeePerUnit + ExitGasPerUnit + ResidualBasisRisk)

がプラスで、かつ許容最小収益(例:0.10%)を超えるときのみ実行します。基準線はイベント・流動性状況で常に変動します。ニュース直後はスプレッドが出やすい一方で、MEV・ガス急騰で実効コストが跳ねるため閾値を引き上げます。

コスト設計(ガス/ブリッジ/スリッページ)

  • ガス:L2のガスは安価でも、混雑時は跳ねます。Priority Feeの上限を決め、過剰な滑りを防ぎます。
  • ブリッジ:公式/サードパーティで料金・到着時間が異なります。遅いブリッジは価格収斂を逃す一方、速いブリッジは手数料が高い傾向。
  • スリッページ:許容幅をタイトにしすぎると未約定・サンドウィッチのリスク増。小刻み分割とクォートサイズ(深さ)の確認は必須です。
  • MEV:サンドウィッチ対策として最小限の可視性(Private Tx / RPCなど)の活用を検討します。

リスクと回避策

  1. ブリッジ遅延・停止:計画より遅延するとヘッジ解消が遅れます。複数ブリッジの冗長性を確保し、最悪は時間切れクローズ。
  2. 価格追随の非対称:CEXに張り付くチェーンと遅いチェーンで乖離が持続。閾値/数量/滞留時間のルール化で対応。
  3. スマートコントラクトリスク:ブリッジ/DEXのバグ・仕様変更。監査状況・TVL・運用実績を常に確認し、資金は分散
  4. ガス急騰/MEV:急なイベントで実効コストが計画を超過。同時両建てと上限コスト設定で被害を限定。
  5. 人的ミス:チェーンやトークンの取り違え。少額テスト → 本番の段階導入を徹底します。

実践プレイブック(ケース別)

ケースA:イベント直後の価格伝播遅延

米雇用統計やFOMC直後はCEXに価格が先行し、L2 DEXの追随が遅れることがあります。数十秒〜数分の窓が狙い目です。割高チェーンで売り、割安チェーンで買い、収斂でクローズします。

ケースB:L2混雑時のガス不一致

片側が混雑しトランザクション詰まりが発生。スリッページを広げずに分割約定で“取りやすい深さ”のみを取りに行きます。

ケースC:プール設計差からの恒常スプレッド

UniV2のプールと集中流動性のV3で価格反応が異なり、薄い時間帯に恒常的な歪みが生まれます。ロットを小さく複数回に分けて回転させます。

自動化:MQL4 EA(プロキシ)/ Pine補助

MT4は直接オンチェーンに接続できないため、プロキシEAとして「同一アセットを異なるブローカーの2銘柄で模擬」し、価格乖離検知と同時両建てのロジックを実装します。考え方の練習としつつ、実運用では自作のオンチェーン実行ロジックに置き換えます。

MQL4(完全自動売買EA)

//+------------------------------------------------------------------+
//|  L2BridgeLatencyArbProxy.mq4                                     |
//|  同一アセットの2銘柄スプレッドを監視し、閾値超えで同時両建て        |
//+------------------------------------------------------------------+
#property strict

input string  SymbolA = "BTCUSD.a";   // 価格が先行する想定の銘柄
input string  SymbolB = "BTCUSD.b";   // 価格が遅れる想定の銘柄
input double  SpreadThreshold = 10.0; // 閾値(価格差, 銘柄のポイント換算)
input double  TakeProfitSpread = 2.0; // 収斂で手仕舞いする差
input double  Lots = 0.10;
input int     Slippage = 5;
input int     Magic = 462015;
input bool    AllowNewTrades = true;

double PointA, PointB;

int OnInit(){
   if(!SymbolSelect(SymbolA,true) || !SymbolSelect(SymbolB,true)) return(INIT_FAILED);
   PointA = MarketInfo(SymbolA, MODE_POINT);
   PointB = MarketInfo(SymbolB, MODE_POINT);
   return(INIT_SUCCEEDED);
}

void OnTick(){
   if(!AllowNewTrades) return;
   if(!IsTradeAllowed()) return;

   double bidA = MarketInfo(SymbolA, MODE_BID);
   double askA = MarketInfo(SymbolA, MODE_ASK);
   double bidB = MarketInfo(SymbolB, MODE_BID);
   double askB = MarketInfo(SymbolB, MODE_ASK);

   // スプレッド(A価格 − B価格)。正ならAが割高。
   double spread = ((bidA+askA)/2.0) - ((bidB+askB)/2.0);
   double th = SpreadThreshold * MathMax(PointA, PointB);
   double tp = TakeProfitSpread * MathMax(PointA, PointB);

   // 既存ポジション確認(片側のみの未整合を避ける)
   int pairs = CountPairs();
   if(pairs == 0){
      // エントリー条件:差が閾値を超える
      if(spread > th){
         // Aを売り、Bを買い
         OpenPair(OP_SELL, SymbolA, Lots);
         OpenPair(OP_BUY,  SymbolB, Lots);
      }else if(spread < -th){
         // Aを買い、Bを売り
         OpenPair(OP_BUY,  SymbolA, Lots);
         OpenPair(OP_SELL, SymbolB, Lots);
      }
   }else{
      // エグジット条件:差が十分に収斂
      if(MathAbs(spread) <= tp){
         CloseAll();
      }
   }
}

int CountPairs(){
   int count=0;
   for(int i=OrdersTotal()-1; i>=0; i--){
      if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;
      if(OrderMagicNumber()!=Magic) continue;
      if(OrderSymbol()==SymbolA || OrderSymbol()==SymbolB) count++;
   }
   // 2で1ペアとみなす(A側・B側)
   return(count/2);
}

bool OpenPair(int type, string symbol, double lots){
   int ticket = OrderSend(symbol, type, lots,
                 (type==OP_BUY)? MarketInfo(symbol, MODE_ASK) : MarketInfo(symbol, MODE_BID),
                 Slippage, 0, 0, "L2Arb", Magic, 0, clrNONE);
   return(ticket>0);
}

void CloseAll(){
   for(int i=OrdersTotal()-1; i>=0; i--){
      if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;
      if(OrderMagicNumber()!=Magic) continue;
      int type = OrderType();
      string sym = OrderSymbol();
      double lots = OrderLots();
      double price = (type==OP_BUY)? MarketInfo(sym, MODE_BID) : MarketInfo(sym, MODE_ASK);
      OrderClose(OrderTicket(), lots, price, Slippage, clrNONE);
   }
}
//+------------------------------------------------------------------+

Pine Script(スプレッドの可視化)

//@version=5
indicator("L2 Arbitrage Spread (Proxy)", overlay=false)
symA = input.symbol("BINANCE:BTCUSDT", "Symbol A")
symB = input.symbol("BYBIT:BTCUSDT",   "Symbol B")
a = request.security(symA, timeframe.period, close)
b = request.security(symB, timeframe.period, close)
// 正規化(%差)
spread = 100.0 * (a - b) / ((a + b) / 2.0)
plot(spread, title="Spread %")
hline(0)
h1 = input.float(0.25, "Entry +%")
h2 = input.float(-0.25, "Entry -%")
hline(h1, color=color.new(color.red, 60))
hline(h2, color=color.new(color.blue,60))

上記はプロキシです。実運用では自前のオンチェーン価格/コスト取得ロジック(複数RPC・プール見積り・ブリッジ料金APIなど)に置き換え、同時実行・部分約定・失敗時ロールバックを実装してください。

検証とモニタリング

  • 事前検証:過去イベント時の価格データを集め、実効コスト込みの理論PnLを算出。
  • 段階導入:極小ロット → 小ロット → 標準ロットの順で上げ、各段階でスリッページ/MEV影響を測定。
  • 継続監視:成功/失敗の原因をラベル付けし、実行基準の再学習を続けます。

チェックリスト

  • 各L2に基準アセットとガス残高を常備
  • DEX承認は事前完了。分割約定の準備
  • 実効価格(スリッページ/ガス/MEV込み)で判定
  • 閾値はイベント時に引き上げる
  • ブリッジの冗長性を確保
  • 記録・分析をルーチン化

FAQ

Q. どのL2の組み合わせが良いですか?
A. 流動性/手数料/ブリッジ速度のバランスで選びます。まずは2–3チェーンで小さく始め、徐々に拡張するのが定石です。

Q. 完全に無リスクですか?
A. いいえ。ガス急騰、ブリッジ停止、スマコン不具合、人的ミスなどの固有リスクがあります。必ず両建て・分散・段階導入で管理してください。

Q. EAだけで本番運用できますか?
A. ここでは考え方の練習用にMT4を用いました。オンチェーン本番は専用実装(ボット)に切り替えてください。

まとめ

Layer‑2間のブリッジ遅延と流動性偏在は、小口でも取りやすい短時間の価格乖離を生みます。勝ち筋は、同時両建て・実効価格基準・厳密なコスト管理・冗長化の4点です。まずは極小ロットで運用手順を体得し、データを蓄積しながら閾値と執行設計を磨いてください。

コメント

タイトルとURLをコピーしました