Bot CEX DEX 戦略ログ 開発ログ

🛠️開発記録#278(2025/8/11)レイテンシ分解:CEX / CEX×DEX / DEXで違う“速さ”——個人botterのための周波数表と設計原則

要旨:高頻度系=「何Hzで意思決定し、どのくらいで手仕舞うか」。まず“頻度レンジ”を決め、そのレンジに合ったレイテンシ分解(md→decide→prelat→req→ack→fill)と**SLO(特にp99)**を置く。そのまま私の実装・運用に流し込めるハンズオン版の設計ガイドとして使う。

本稿で使う「周波数」と「周波数帯」

  • 周波数(Hz)=「1秒間に、意思決定→(必要なら)発注/取消のループを何回回すか」。
    数式:f_decision = 1 / T_decision(T_decision は主に md→decide→prelat の反応周期)
  • 周波数帯=上の周波数をレンジで区分した運用の帯。本記事では A-0〜C-2 を使い、帯ごとに設計・KPI・安全装置のプリセットを変える。

混同しやすいもの】

  • 周波数 ≠ 注文レート(注文件数/秒)。発注しない判断も“1回の意思決定”。
  • 周波数 ≠ 市場データのサンプルレート。板イベントはもっと高頻度に来る。
  • 実効ループ時間は反応だけでなくネット往復の遅い方で決まる:
    実効ループ ≈ max( T_decision, p99(send→ack), p99(cancel RTT) )

早見換算(反応周期→周波数)

  • 5 ms ≈ 200 Hz / 50 ms ≈ 20 Hz / 100 ms ≈ 10 Hz / 250 ms ≈ 4 Hz / 1 s ≈ 1 Hz

文脈別の読み替え

  • CEX(連続時間/A-2:50–200ms → 5–20Hz)
    目標は send→ack p99cancel RTT p99 を反応周期と同じ桁に抑えること。
  • CEX×DEX(裁定/100–300ms → 3–10Hz)
    時刻差ゲート ≤ 250ms を置き、同時性が崩れた見積もりを排除。
  • DEX(離散時間)
    有効周波数 ≈ 1/スロット時間。C-1(L1)≈0.08Hz、C-2(高TPS)2–20Hz。
    実効性は pre-sim成功率bundle遅延 にも左右される。

運用指針(手短に)

  1. 周波数帯を選ぶ(A-2/B/C-2 のどれで戦うか)
  2. 帯に合わせて SLO を置く(例:send→ack p99 ≤ 250ms、cancel p99 ≤ 250ms)
  3. 反応周期往復p99遅い方から削る
  4. 評価は **分布(P50/P95/P99)**で。平均は封印

はじめに:なぜ“分解”が勝ち筋になるのか

要点:速さの絶対値よりも、どの区間が遅いか(そして“いつだけ遅いか”=テール)が P/L を決めます。とりわけキャンセルRTTの p99は、キュー位置(queue position)と逆選択コストに直結します。だから最初に tick-to-trade を区間に分解し、各区間の分布(P50/P95/P99/P99.9)で管理するのが最短ルートです。


1) P/L は“キュー位置 × 逆選択”で決まる

リミット注文は価格→時間優先で並び、先頭ほど価値が高い。学術的にも、注文のキュー位置の価値は定式化され(先頭ほど早く約定し、逆選択リスクも低い)、位置を守る(=遅れて並び直さない)ことが利得に効くと示されています。つまり、キャンセルや再提示が速いほど「良い位置」を維持しやすい、という構造です。
moallemi.com
SSRN
サイエンスダイレクト


2) “速度の腕相撲”が起きる理由(設計由来の現象)

連続取引(CLOB)ではわずかな速度差スナイプ(先回り)を生み、マイクロ秒~ミリ秒の争いが合理化されます。市場設計の観点からも、これは市場デザイン由来の腕相撲であり、時間を離散化するFrequent Batch Auctionsが提案されるほど(微差の速度優位を弱めるため)。この文脈は“速度が P/L に効く”ことの理論的裏付けになります。
Oxford Academic
AQRキャピタルマネジメント
ericbudish.org


3) だからこそ“キャンセルRTTの p99”が重い

逆選択コスト(約定直後に不利方向へ動くリスク)は、不利な兆候を検知してからキャンセルが完了するまでの遅れに強く依存します。研究でも、レイテンシはリミット戦略の価値を侵食し、「見込み悪化を察してどれだけ早く引けるか」が EV を左右することが示されています。ここで効くのは平均ではなくテール――**たまの“極端に遅いキャンセル”**が大きな損失を作るため、p99/p99.9を短く静かに保つ設計が要点になります。arXiv


4) “平均は嘘をつく”:分布(Pxx)で運用する

レイテンシは形(分布)で語るべきで、平均は現実を隠します。特にコーディネーテッド・オミッション(計測側が遅延を取りこぼす偏り)は、見かけの平均や分位点を過小評価させます。運用では、**ヒストグラム→サーバ側の分位点(P99/P99.9)**を出し、テールの変化を監視してください。
videog.infoq.com
Google グループ


5) 実務に落とすと何が変わるか(指針)

  • 区間分解md→decide / decide→send / send→ack / ack→fill / cancel RTT別々に計測
  • SLO は p99 基準:例)send→ack p99 ≤ 250mscancel RTT p99 ≤ 250ms
  • 改善の順序
    1. キャンセルRTTの p99(=キュー位置の維持/逆選択の抑制)
    2. send→ack の p99(ネット/経路)
    3. md→decide の p99(実装/GC/ロック/アロケ)
  • 評価は EV 分解:Spread/Fee/Slip/逆選択/失敗コストにブレークダウンし、テール改善が P/L に効いたかを確かめる

参考・参照

  • キュー位置の価値:Moallemi ほか “A Model for Queue Position Valuation in a Limit Order Book”(queue 前方の経済的価値を定式化)。
    moallemi.com
    SSRN
  • キュー位置と逆選択:最新の実証的/理論的報告(キュー位置は逆選択リスクに影響)。サイエンスダイレクト
  • レイテンシが戦略価値を侵食:Stochastic control の観点からキャンセル遅延が EV を下げるメカニズム。arXiv
  • 速度競争の市場設計的説明:Budish–Cramton–Shim(QJE)“HFT Arms Race / Frequent Batch Auctions”。
    Oxford Academic
    AQRキャピタルマネジメント
  • “平均は嘘/テールを見よ”:Gil Tene “How NOT to Measure Latency” とCoordinated Omissionの警鐘。
    videog.infoq.com
    Google グループ

この前提を頭に置いて、以降のセクション(計測・頻度レンジ・CEX/CEX×DEX/DEX実装)を“p99 を静かにするための分解”として読むと、改善の優先順位が自然に定まります。

全体像:md→decide→prelat→req→ack→fill(どこを測る?)

flowchart LR
subgraph TTT["Tick-to-Tradeレイテンシ分解"]
MD(["md受信"])
DECIDE["md→decide(戦略/リスク)"]
DONE(["見積/判断完了"])
PRELAT["prelat(署名/整形/キュー)"]
SEND(["送信write"])
REQACK["req→ack(ネット/取引所)"]
ACK(["ACK"])
FILL["ack→fill(実約定/取消)"]
MD --> DECIDE --> DONE --> PRELAT --> SEND --> REQACK --> ACK --> FILL
end

計測点(Prometheus例)

  • mm_md_to_decide_seconds(md→decide)
  • mm_decide_to_send_seconds(prelat)
  • mm_send_to_ack_seconds(req→ack)
  • mm_ack_to_fill_seconds(ack→fill)
  • mm_cancel_rtt_seconds(取消往復)
  • mm_tick_to_order_seconds(md→送信write)

計測のコツ

  • ハードウェアタイムスタンプ+PTP同期(μs精度の地図を作る)
  • 分布で見る(P50/P95/P99/P99.9)。平均は封印

深掘り:計測点(Prometheus 例)—定義と実装

まず、イベント境界の“生の時刻”を決めます(名称は例)。

  • t_md_rx:市場データ受信時刻(RXハードウェアTSが理想)
  • t_decide_end:戦略・リスク判定完了
  • t_send_write:送信 write 提出(TXハード/ソフトTSが理想)
  • t_ack:ACK 受信(RXハードTS
  • t_fill:Fill/取消 受信(RXハードTS

この 5 点を使って、次の ヒストグラムを記録します(単位は秒):

  • mm_md_to_decide_seconds = t_decide_end − t_md_rx(md→decide)
  • mm_decide_to_send_seconds = t_send_write − t_decide_end(prelat)
  • mm_send_to_ack_seconds = t_ack − t_send_write(req→ack)
  • mm_ack_to_fill_seconds = t_fill − t_ack(ack→fill)
  • mm_cancel_rtt_seconds = 取消送信→取消ACK の往復
  • mm_tick_to_order_seconds = t_send_write − t_md_rx

推奨ラベル

{pair="BTCUSDT", venue="binance", side="buy|sell", mode="prod|canary"} 程度に最小限。取引IDやオーダーIDをラベルに入れるのはNG(高カーディナリティ地獄)。

バケットの初期値

[0.001, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1]
A-2/B/C-2 レンジ(p99≤250ms 目標)に合う粒度。Prometheus はヒストグラムからサーバ側で分位点を算出でき、レプリカ横断の集計に強いです。要件に応じて境界は“観測値に合わせて”調整してください。Prometheus


実装スニペット(Rust/Python のどちらでも同趣旨)

Rust(prometheus crate 例)

use prometheus::{register_histogram, Histogram};

lazy_static::lazy_static! {
    static ref SEND_TO_ACK: Histogram = register_histogram!(
        "mm_send_to_ack_seconds",
        "order send -> ack",
        vec![0.001,0.005,0.01,0.025,0.05,0.1,0.25,0.5,1.0]
    ).unwrap();
}

// 計測例
fn on_ack(t_send_write: f64, t_ack: f64) {
    SEND_TO_ACK.observe(t_ack - t_send_write);
}

Python(prometheus_client 例)

from prometheus_client import Histogram
send_to_ack = Histogram(
    "mm_send_to_ack_seconds", "order send -> ack",
    buckets=[0.001,0.005,0.01,0.025,0.05,0.1,0.25,0.5,1.0]
)
def on_ack(t_send_write, t_ack):
    send_to_ack.observe(t_ack - t_send_write)

備考:クライアント実装ごとにデフォルトのバケットは異なります(例:Python と Go で差あり)。自分のレイテンシ分布に合わせて必ず上書きしてください。Medium


PromQL(ダッシュボード&アラート)

p99(5分窓)

histogram_quantile(0.99,
  sum(rate(mm_send_to_ack_seconds_bucket[5m])) by (le)
)

ヒストグラムはサーバ側で分位点計算インスタンス横断の集計が可能。一方、Summary の分位点は基本集約不可です。全体 p95/p99 を出す運用なら Histogram を選びましょう。Prometheus

SLO 監視例

  • Warn: histogram_quantile(0.99, sum(rate(mm_send_to_ack_seconds_bucket[5m])) by (le)) > 0.150
  • Page: … > 0.250 が 5 分継続

計測のコツ

1) ハードウェア・タイムスタンプ(NIC)を使う

SO_TIMESTAMPING / SOF_TIMESTAMPING_*RX/TX のハードウェア時刻を受け取り、recvmsg()cmsg(エラーキュー含む)から読むのが最短・最正確です。ts[2] に HW TS が入り、TX は MSG_ERRQUEUE で回収します。SOF_TIMESTAMPING_OPT_ID を付けておくと、send() と TS の対応付けが頑強になります。docs.kernel.org

ポイント

  • RX:t_md_rx/t_ack/t_fillRX ハードTS を採用
  • TX:t_send_writeTX ハード/ソフトTS(可能ならハード)で取得
  • 平均ではなく、区間差分を出してヒストグラムへ

2) PTP(linuxptp)でクロック同期

ptp4l で NIC の PHC(PTP Hardware Clock) をマスターに同期し、phc2sysPHC→システム時刻を引き当てます。ハードウェアサポート時はサブμs級の精度が狙え、NTP より高精度。NIC が HW TS を持つかは ethtool -T で確認できます。Red Hat Documentation

  • 確認ethtool -T eth0SOF_TIMESTAMPING_{TX,RX}_HARDWARE / PTP Hardware Clock が出ることを確認。Red Hat Documentation
  • 起動例ptp4l -i eth0 -m(既定で HW TS を利用)→ phc2sys -a -r(PHC と System を同期)Red Hat Documentation
  • 注意同時に NTP と競合させない(片方に寄せる)。Red Hat Documentation

なぜ PTP?
ハードウェア支援の PTP は サブ μs の同期が可能(LAN/NIC 次第)。NTP は通常 ms 級が目安。
Red Hat Documentation
Quantum

3) 分布で見る(P50/P95/P99/P99.9)—平均は封印

平均は真実を隠す、特に**尾(tail)**が重要。Gil Tene の名講演どおり、分布(分位点)と尾の動きで語りましょう。可視化は Histogram+histogram_quantile() を基本に。
YouTube
bravenewgeek.com


よくある落とし穴(対策付き)

  • 異なるクロックを混ぜる
    送受信は HW TS(PHC 系)、アプリ内部は(同一プロセス内の)monotonicで OK。ただし区間同士を比較する時は同源のクロックで差分を取る。
  • Summary を使って全体 p99 を出そうとする
    レプリカを跨いだ分位点の集約は壊れる → Histogram を使うPrometheus
  • バケットが実態に合っていない
    初期は広めに置き、観測分布に合わせて境界を調整(p99 近辺に細かく)。デフォルト値に過信は禁物。
    Prometheus
    Medium
  • TX タイムスタンプの取りこぼし
    TX の HW/ソフト TS は エラーキューから回収(recvmsg(MSG_ERRQUEUE))。SOF_TIMESTAMPING_OPT_ID を付け、順序入れ替えでも照合できるように。docs.kernel.org

仕上げのチェックリスト

  • t_md_rx / t_send_write / t_ack / t_fillHW TS で刻めている
  • Prometheus は Histogramで、send→ack/cancel RTTp99 を表示
  • ptp4l + phc2sys が同期中、ethtool -T に HW TS 能力が出ている
  • p99 アラート(Warn 150ms / Page 250ms)が動作
  • バケット境界は実測分布に合わせて見直し済み

参考・参照(出典)

  • Linux ネットワーク・タイムスタンプ(SO_TIMESTAMPING):ハード/ソフト TS の意味、MSG_ERRQUEUE での TX TS 取得、SOF_TIMESTAMPING_OPT_ID 等のオプション説明。docs.kernel.org
  • PTP(linuxptp):サブ μs 級の同期、ptp4l/phc2sys の役割、ethtool -T での能力確認、NTPと同時使用の注意。Red Hat Documentation
  • Prometheus:Histogram vs Summary(分位点集計・バケット選定の考え方、histogram_quantile() 例)。Prometheus
  • バケット初期値と落とし穴(クライアント実装のデフォルト差異の注意)。Medium
  • “平均は嘘をつく/テールを見る”(Gil Tene 講演、テール重視の重要性)。
    YouTube
    bravenewgeek.com

この設計でダッシュボードを作れば、p99 のテール部分が何に由来するか(戦略?署名?ネット?取引所?)がクリアに見えて、次のチューニングの優先順位が決めやすくなります。


頻度レンジの定義(周波数表)

ラベル反応周期(decision cadence)req→ack 目安保有典型個人の現実性
A-0 超HFT5–500µs0.1–2ms10–500msイベント・スナイプほぼ不可
A-1 低ms1–10ms1–5ms0.2–2s先頭キュー争い
A-2 HFT-lite50–200ms50–250ms1–30sメイカー寄りMM主戦場
B CEX×DEX100–300ms0.5–10s(ヘッジ完了まで)裁定主戦場
C-1 DEX L1ブロック秒(≈12s/slot)ブロック〜数分清算/JIT流動性
C-2 高TPS50–500ms(例:slot≈400ms)1–30sAMM裁定/再配分主戦場

目安の根拠
・A-0〜A-1のμs〜低ms世界は、実測でFIXパケット間p50≃9.5µs / p99≃25µsなどが公開されており、コロケ前提の超低遅延領域です。epamsolutions.a.bigcontent.io
・C-1(Ethereum PoS)は1 slot ≈12秒、C-2(Solana)はslot≃400–600msが公式に説明されています。
Alchemy
solana.com
・B(CEX×DEX)は都市間RTTが基礎で、たとえば東京↔シンガポールは≃65–72msが現実レンジです(測定系2種の公開値)。
WonderNetwork
Verizon


A-0 超HFT(5–500µs / req→ack 0.1–2ms)

何をやる帯? ニュース/イベント着火、板更新への即応スナイプ、先頭キューの恒常確保。
必要条件 コロケ+特殊NIC/FPGA+カーネルバイパス。FIXパケット間p99≃25µs級の世界。epamsolutions.a.bigcontent.io
KPI tick→orderorder→tickµs分解、IRQ/NUMAジッタの消し込み。
個人の現実性 ほぼ不可(費用と接続制約)。
備考 超HFTが価値を取る仕組み(キュー位置=利得、レイテンシ・アービトラージ)は学術的にも整理済み。
Oxford Academic
strategicreasoning.org

A-1 低ms(1–10ms / req→ack 1–5ms)

何をやる帯? 先頭キュー争いをソフト実装だけで狙う層。
必要条件 同DC/準コロケ、Onload/AF_XDP 等の最短経路、Order↔Tickのµs級を継続観測。ember.deltixlab.com
KPI md→decide ≤ 1–2ms / decide→send ≤ 1ms / send→ack p99 ≤ 5ms
個人の現実性 難(接続・席料・運用の壁)。

A-2 HFT-lite(50–200ms / req→ack 50–250ms)

何をやる帯? メイカー寄りMMで逆選択を抑えつつ回す“個人の主戦場”。
設計の肝 send→ack / cancel RTTp99短縮(= キュー位置の維持)。
KPI send→ack p99 ≤ 250mscancel RTT p99 ≤ 250msslip p95 ≤ 1–2bp
勝ち筋 post-only(LIMIT_MAKER)、cancelReplace、価格コリドー、露出上限。
裏付け(Bレンジも含め)東京↔シンガポールの実RTT≃65–72msを起点に“全体p99≦250ms”は現実的。
WonderNetwork
Verizon

B CEX×DEX(100–300ms / ヘッジ完了0.5–10s)

何をやる帯? 実効単価の同時比較による裁定(CEX L2→VWAP vs DEX Aggregator Quote)。
設計の肝 時刻差ゲート ≤ 250ms(同時性が崩れた見積りを切る)、最速勝ち並列でstale排除。
KPI stale_rate / dex_quote_ttl_ms / hedge_gap_ms / arb_ev_bp
勝ち筋 FX(USDT/USDC)基差の常時計測、失敗時は即キャンセル/ヘッジでΔ凍結。
現実性 高(インターネット遅延の範囲で成立)。

C-1 DEX L1(ブロック秒 ≈ 12s/slot)

何をやる帯? 清算スナイプJIT流動性など、同一ブロック内の実行確度がすべて。
前提 Ethereumは1 slot ≈ 12秒(PoS)。ブロック伝播・アテステ含む時間地図を理解して設計。
Alchemy
Blocknative
KPI pre-sim→exec success% / sandwiched% / bundle latency
勝ち筋 pre-sim→private送信(Protect系)→ガス階段。
現実性 可(研究+検証の投資は必要)。

C-2 高TPSチェーン(50–500ms / 例:slot≃400–600ms)

何をやる帯? AMM裁定、v3系LPの帯域再配分とΔヘッジなど、サブ秒で反応できる設計。
前提 Solanaのslotは約400ms(状況で〜600ms)。**blockhash期限≃1分(150ブロック)**など時間ルールも合わせて設計。solana.com+1
KPI bundle/route latency / failed_tx% / lp_fee_apr / gamma_pnl
現実性 高(クライアント最適化+並列安全装置で十分戦える)。


周波数→Hz 早見

5ms≈200Hz / 50ms≈20Hz / 100ms≈10Hz / 250ms≈4Hz / 1s≈1Hz。
意思決定の周波数保有時間の組合せで“自分の帯”を固定してから、KPIと設計(レイテンシ分解、A/B軸、ガード)を選ぶのが最短です。


推奨KPI(帯ごとのフォーカス)

  • A-2 / B / C-2(主戦場): send→ack p99, cancel RTT p99, slip p95, stale_rate
  • C-1: pre-sim→exec success%, sandwiched%, bundle latency
  • 全帯: 分布で運用(P50よりP99、P99.9も監視)

参考・参照

  • Ember(EPAM)計測:FIXパケット間 p50≃9.5µs / p99≃25µs など、超低遅延ベンチ。
    epamsolutions.a.bigcontent.io
  • Order↔Tick µs測定(Ember Trade Hub):クライアント群の実測例。ember.deltixlab.com
  • Ethereum PoS の時間構造slot≈12秒の定義と開発者向け解説。
    Alchemy
    Blocknative
  • Solana の slot/ブロック時間slot≃400–600msと有効期限の仕様。solana.com+1
  • 都市間RTTの実測:東京↔シンガポールの~65–72ms(測定サービス/キャリア発表)。
    WonderNetwork
    Verizon
  • レイテンシ・アービトラージの学術的整理:速度優位とキュー位置の価値。
    Oxford Academic
    strategicreasoning.org

KPI設計:P50/P95/P99、バケット、アラート

推奨SLO(まずはここ)

  • send→ack p99 ≤ 250ms
  • cancel_rtt p99 ≤ 250ms
  • slippage_p95 ≤ 1–2bp
  • stale_rate ≤ 1%(CEX×DEX)

ヒストグラム例(秒)
{0.001, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1}

アラート例

  • Warn: send→ack p99 > 150ms(24h moving)
  • Page: send→ack p99 > 250ms or cancel_rtt p99 > 250ms 連続5分

速度の事実:μs世界 vs インターネット世界/戦場の選び方

以下は私的なメモとTo Do。

  • μs世界(コロケ・FPGA)は設備ゲー。個人は深入りしない。
  • インターネット世界(A-2/B/C-2)はp99の尻尾を刈れば十分戦える。
  • 戦略は「P50を誇るよりP99を静かに」に寄せる。


CEX(現物MM:A-2レンジ)

勝ち筋(要約)

  • 逆選択コスト最小化キュー位置の維持=利益源を守る
  • p99の短縮とpost-only運用で“並び直し”を減らす

実装要点

  • WS発注(RESTはフォールバック)
  • **LIMIT_MAKER(post-only)**でメイカー保証
  • **cancelReplace**でワンショット再見積もり
  • **STP(自己約定防止)**モード有効化
  • レート重み制御:レスポンスヘッダで使用量をフィードバック
  • オーダーブック:SoA+固定長リング、差分は無アロケで適用
  • プリトレード・リスクはインプロセス関数1発(名目上限、価格コリドー、1サイクル新規/取消上限)

ガード

  • 価格コリドー(基準価格±kσ/±bp外は発注拒否)
  • 露出上限LIVE_MAX_NOTIONAL_USD、並列数上限)
  • 連続staleで30sクールダウン
  • JST日次リセット(連敗カウンタ/PnLを0化)

ダッシュボードKPI(目安)

  • cancel_rtt p99 ≤ 250ms / send→ack p99 ≤ 250ms
  • maker_fill逆選択比率 の低下(週次A/Bで監査)
  • OTR(Order/Trade)を健全レンジに(例:5–20:1)

CEX×DEX(クロスマーケットアービトラージ:Bレンジ)

要点

  • 同時比較:CEX(L2→VWAP) vs DEX(aggregator quote) の実効単価
  • 時刻差ゲート|t_cex - t_dex| ≤ 250ms 以内だけ約定候補
  • Hedged並列クオート:複数アグリゲータに並列→最速勝ち、遅延応答は中断

EV式(実行期待値)

EV_bp = exec_spread_bp
        - fee_bp
        - gas_bp
        - slip_bp
        - fx_basis_bp
        - fail_cost_bp

fx_basis_bp は USDT/USDC の板実測から常時計算・保存

失敗時の凍結(フォールバック)

  • DEX送信失敗 → CEX即キャンセル or Perp微量ヘッジでΔを凍結
  • すべて1関数で分岐確定(外部RPC禁止)

監視

  • stale_rate / dex_quote_ttl_ms / hedge_gap_ms / arb_ev_bp
  • ガス急騰時の自動停止、MEV多発時はprivateルート送信

DEX(オンチェーン単独:C-1/C-2)

清算スナイプ/状態変化系

  • mempoolクラスタリング(遅延到着はReorder Bufferで吸収)
  • pre-sim必須(pending stateを含む正確なシミュ)
  • private送信(Protect等)+ガス階段で競争に勝つ

v3 LP(集中流動性)

  • 帯域再配分(中心価格±kσ、ボラ/流入で帯域幅を自動調整)
  • Δヘッジ(現物/Perp微量)で**曲率(Γ)**収益を守る

KPI

  • sim→exec success% / sandwiched% / gas_per_fill / lp_fee_apr / bundle_latency_ms

OS/ネットワーク最適化(A-2/B/C-2で効く“現実解”)

  • busy-polling(対象ソケット限定)で割り込み/文脈切替を抑制
  • IRQ/スレッドのピン留め(NUMA跨ぎ禁止、戦略/MD/送信のコア固定)
  • PTP + HWタイムスタンプSO_TIMESTAMPING
  • mlockall / スワップ無効coalescingの見直し(A/Bで最小化)
  • TCP_NODELAY、キュー深さの適正化、1段少ない配線経路

無アロケ&ロックレス(Rustデータプレーン)

  • 単一ライター+リングバッファ(Disruptor流)でロック排除
  • バッファ再利用(署名/エンコード用の固定領域、ホットパスnew禁止)
  • SoA構造(価格配列/数量配列)とキャッシュ局所性
  • バイナリプロトコル(SBE/Protobuf)。JSON必須ならsimd系でストリーミング
  • Python側は非同期メッセージング(pyo3/gRPC/ZeroMQ)で絶対にブロックしない

A/B実験設計(Fill品質とCancel p99を同時に見る)

  • 因子:post_only ∈ {on,off} × notional ∈ {S,M,L} × vol_regime ∈ {low,mid,high}
  • 主要指標:cancel_rtt p99 / fill逆選択率 / slip_p95 / net_PnL_per_notional
  • ルール:1セッション1因子変更期間を揃えるEV分解で解釈(Spread/Fee/Slipを別集計)

まとめ:“測る → 尾を刈る → 戦場を選ぶ”

  • 測る:区間別P99を常時可視化
  • 尾を刈る:キャンセルRTTとsend→ackのテールから
  • 戦場を選ぶ:A-2/B/C-2に集中し、p99≤250msの世界で勝つ


付録A:Prometheusメトリクス名(例)

mm_md_to_decide_seconds{pair="BTCUSDT"}
mm_decide_to_send_seconds{pair="BTCUSDT"}
mm_send_to_ack_seconds{pair="BTCUSDT"}
mm_ack_to_fill_seconds{pair="BTCUSDT"}
mm_cancel_rtt_seconds{pair="BTCUSDT"}
mm_tick_to_order_seconds{pair="BTCUSDT"}

arb_ev_bp
dex_quote_ttl_ms
stale_rate
hedge_gap_ms
slippage_bp
maker_adverse_fill_ratio

Bucket例(Rust/Go/Pythonいずれも同値を採用)
[0.001, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1]


付録B:即実行チェックリスト(今日〜明日)

計測

  • PTP+HWタイムスタンプで区間P99を出す
  • send→ack/cancel_rttP50/P95/P99をダッシュボード化

CEX

  • 発注をWSに一本化、**LIMIT_MAKERcancelReplace**徹底
  • STP有効化、newClientOrderIdで冪等化
  • 価格コリドー/露出上限/連続staleクールダウン導入

CEX×DEX

  • Hedged並列クオート(最速勝ち・遅延中断)
  • 時刻差ゲート≤250msfx_basis_bpの常時計測
  • 失敗時ハンドラ(即キャンセル/ヘッジ)を1関数で確定

DEX

  • mempoolクラスタ→pre-sim→private送信を“通行証”化
  • ガス階段・sim→exec success%監視・sandwiched%低減

OS/ネットワーク

  • busy-poll(対象限定)/IRQ pinmlockallcoalescing最小でA/B
  • NIC/スレッドのNUMA跨ぎ禁止を確認

このまま運用に載せて、p99の尻尾が落ちる→逆選択が減る→キュー位置が上がるの順に効かせる。

-Bot, CEX, DEX, 戦略ログ, 開発ログ