今日は基盤を育てつつ開発の方針も根本から見直すこともした日でした。
“稼げるか”証明が私の現在の課題で、この部分が足を引っ張ってbotの開発が目標値の30〜40%程度の達成度になっています。
これらのbotの最小Liveを回してEV>0を証明するまで、全体であと3〜6週間程度はかかる見通しなので、引き続き他の戦略を実行するbotの開発も継続して、使える武器を増やしていきます。
流石に5つも異なる種類のbotを並行開発しているとどの戦略(≒bot)が筋が良いのか(悪いのか)を俯瞰できるようになってくる。
その時に有効な戦略は開発がサクサク進むし、運用に乗せるまでも早い。そうでないものはいつまで経っても存在しない(かもしれない)アルファを延々探し続けることになる。— よだか(夜鷹/yodaka) (@yodakablog) August 20, 2025
MMbot:開発ログ&サマリ
- できていること
- Exporterを**単一HTTPサーバ(MMBotHTTP/1.0)**に統一。
/metrics
稼働、/control
(enable/disable)200応答。 - KPI設計と実装の整備:
mm_ev_order_attempt_total / mm_ev_order_total(ACK)/ mm_ev_reject_total
の語義分離完了。 - レイテンシ計測の基盤:
mm_lat_request_to_ack_seconds / mm_lat_total_seconds / mm_cancel_rtt_seconds
を追加。 - ビルド/環境情報:
mm_build_info{env,sha,base}
露出。 - UserStream(ListenKey取得+WS接続・二段フェイルオーバ、fill捕捉)を実装しRunnerに統合。
- ドキュメント/方針の転換:**常時パッシブMM→ゲーティッドMM+反転/裁定(二刀流)**へ。
- Exporterを**単一HTTPサーバ(MMBotHTTP/1.0)**に統一。
- 詰まっていること(ブロッカー)
- ネットワーク:ホストでも
https://api.binance.co.jp/api/v3/time
が timeout(上位FW/ISPの443 egress制限)。 - 監査ログ:
/metrics
のACCESSは出るが、/control
のログ可視が不安定(機能は200応答)。 - 実データ:上記①のため Canary未通電→段別ヒストはBOOT以外のサンプル未採取、UserStream動作も未検証。
- ネットワーク:ホストでも
- 今日のゴール
**「1本通す→計測→止める」**を確定させる。= 443疎通(code:200)→place_canary
→ 段別ヒスト増分 →/am-webhook
停止。
1. タイムライン(主要イベント)
- 初期不具合の収束
-2014 API-key format invalid
:Global→Japanエンドポイント混在、API鍵未設定を解消。- PYTHONPATHの実行パス齟齬(
/app/src
vs/app/mm_bot
)/古いイメージ参照/ProcessLockを解消。
- Exporterの統一
prometheus_client.start_http_server
依存を廃止し、ThreadingHTTPServerで/metrics
/control
/am-webhook
を一元。attach_runner(self)
で Runnerインスタンス直参照を保証。
- /control の 405解消 → 200応答
@api_route("/control", methods=["GET","POST"])
→のち単一サーバ実装へ移行。- enable/disable の理由ログ/カウンタは配線済み。
- KPIの語義修正(重要)
mm_ev_order_attempt_total
:送信試行回数mm_ev_order_total
:ACK成功のみmm_ev_reject_total
:拒否/例外
→ 以前の「送信時に order_total++」をACK後に限定。
- 観測・レイテンシ基盤
- ヒストグラム:
request→ack / total / cancel_rtt
を追加。 mm_build_info{env,sha,base}
露出。
- ヒストグラム:
- UserStream 実装
- JP RESTで ListenKey、WSは
wss://stream.binance.co.jp/ws
→ 失敗時wss://stream.binance.com:9443/ws
の二段接続。 - executionReport(TRade)で
mm_ev_fill_total
、PnL器(fees/spread
)へ加算。Runnerへ統合。
- JP RESTで ListenKey、WSは
- 戦略の刷新
- 常時パッシブMMをやめ、SpreadExcursion gate+短TTLのAGMMと、反転クォート BRQの二刀流へ転換。
- Go/No-Go基準(Paper 24–48h:EV>0 / Fill≥35% / Reject≤3%)を確立。
2. 現在のシステム構成(抜粋)
- コントロール:
/control
(POST):enable_live / disable_live / place_canary
- メトリクス:Prometheus pull(8080),主なメトリクス
- 制御:
mm_control_actions_total{action=...}
/mm_status_new_orders_enabled
- KPI:
mm_ev_order_attempt_total / mm_ev_order_total / mm_ev_reject_total / mm_ev_fill_total
- PnL(器):
mm_pnl_components_total{kind∈[fees,spread,slippage,adverse]}
- レイテンシ:
mm_lat_request_to_ack_seconds
/mm_lat_total_seconds
/mm_cancel_rtt_seconds
- ビルド:
mm_build_info{env,sha,base}
- 制御:
- 停止:Alertmanager →
/am-webhook
→disable_live
(ログ+カウンタ)
3. 完了タスク / 未完タスク
完了
- Exporter統一(MMBotHTTP/1.0)/Runner attach
/control
機能(200応答)- KPI語義分離(attempt/ack/reject)
- レイテンシ・ビルド情報の露出
- UserStream 実装+Runner統合(接続ロジック・二段WS)
- 方針刷新(AGMM+BRQ)とドキュメント反映
未完(ブロッカー含む)
- ネットワーク疎通:ホストでも
api.binance.co.jp:443
timeout(FW/UTM/ISP) - /control監査ログの安定化:
ACCESS
などのログが常に見える状態へ(現状APIは返るがログが無音なケースあり) - Canary 1本通電:
mm_ev_order_total
を ACKで +1 - 段別ヒストの“実”サンプル:BOOT以外の増分
- UserStream 実接続検証:
mm_ev_fill_total
増分確認
4. 不可解点(原因仮説と一次切り分け)
- /control ログ無音
- 機能は200返却。ログが無音=ハンドラ冒頭のログが出ていない
- 仮説:
do_POST
以外(GET)で叩いている/logger.propagate=False
/basicConfig(force=True)
が起動順で未適用/grepパターン不一致 - 一次切り分け:ハンドラ冒頭で print + logger、
log_message()
オーバーライド、POSTで打鍵、レスポンスにts / exporter_id
を返す
- 443 timeout(ホストでも)
- Docker以前。上位FW/回線の 443 宛先制限が本丸。
- 暫定:別回線/Cloud VM/(Linuxなら)
network_mode: "host"
で「まず1本」を通す。
- Shadow混入の懸念
place_canary
本文はOK。呼び出し前の mode 分岐で早期returnがないか、ランタイムの本文表示で確認済。
5. 受入基準(本フェーズ)
- /control:
POST
→ ACCESSログ or 理由ログ1行、mm_control_actions_total
増分、mm_control_last_ts_seconds
更新 - ネット:ホストで
https://api.binance.co.jp/api/v3/time
→ code:200 - Canary:
mm_ev_order_attempt_total≥1
かつmm_ev_order_total≥1
(ACKベース)、mm_lat_request_to_ack*_bucket
が非BOOT増分 - UserStream:
userstream connected ...
がログに1行、mm_ev_fill_total
増分(自然fill もしくは暫定IOCで1件)
6. 改善フロー(直近 60–90分)
- 443疎通(最優先)
- ホストで code:200 を先に出す(別回線/Cloud VM/host network)。
- /control ログの可視化
- ハンドラ冒頭の print+logger、
log_message()
、レスポンスにts / exporter_id
。
- ハンドラ冒頭の print+logger、
- Canary 1本 → 段別ヒスト増分
- ACKで
mm_ev_order_total++
。
- ACKで
- UserStream 生存監視
mm_health_userstream_up
を 0/1 で露出、接続ログを1行。
7. 戦略面の整理(ゲーティッドMM+BRQ)
- AGMM(Alpha-Gated MM)
- SpreadExcursion gate:直近15分 p80×1.5 以上だけ ON
- TTL撤退:500ms(Vol高→700–900ms/低→350ms)
- 片翼・裏置き:BOB/BOA基準、α弱い時は1–2ティック裏
- BRQ(Burst Reversion Quoter)
- 短窓 OFI×微反転で“瞬間”置き → TTL短め
- 在庫スキュー:
size = base * (1 - β*inv_ratio)
(β≈0.6 初期) - Go/No-Go:Paper 24–48h → EV>0 / Fill≥35% / Reject≤3%
8. 付随の運用ベストプラクティス
- Day-0チェック(起動直後に5秒):
/control POST=200 / runner_attached / mm_bot path=/app/mm_bot / base_url=co.jp / exchange time=200
- Exporter単一宣言:メトリクス定義は1ファイルのみ。他は import して
.inc()
/.set()
。 - SecretsはENV。
/metrics
にcfg_has_keys
だけ露出。 - 再作成コマンドの固定化:
docker compose rm -sf mmbot && docker compose up -d --build --force-recreate mmbot
9. いまの到達度(“稼ぐ”をゴール)
- 実行/可視化:~70%(Exporter統一・KPI/レイテンシ露出、制御200)
- リスク/停止:~60%(Webhook→停止OK、監査ログの安定化が残り)
- EV実証:~20%(疎通ブロックでCanary未通電、実サンプル未採取)
- 総合:≈55%(±5%)。疎通を解けば一気に上がる位置。
10. 次の一手(超短縮版)
- 回線/上位FWで
api.binance.co.jp:443
の許可 → ホストで code:200。 - /control ログを必ず1行出す(ハンドラ冒頭+メトリクス補助+レスポンス足跡)。
place_canary
→attempt/order
増分、段別ヒストの実増分。- UserStream 接続ログ →
mm_ev_fill_total
を1件でも立てる。
→ ここまで通ったら、AGMM/BRQの初期パラメータ(bp/TTL/在庫β)をメトリクス分布から即チューニングします。
MMbot:筋悪ポイント&改善ポイント(TL;DR)
- 最大のズレ: 「EVが立つ場にいないのに、インフラを先に磨いた」。
- 戦略の根本: 手数料10bpsのBTC/JPY現物で常時パッシブMMは数学的に負け筋。
- 実装順序: Canary→Fill→EVの三点セットを先に固めず、Exporterやログ体裁に多くの時間を費やした。
- 運用判断: 443疎通(回線)を最初に潰さなかったため、「1本通す」までが遅延。
1) 戦略選定の筋が悪い点
- 常時パッシブMM(BTC/JPY・maker 10bps・リベート無)に固執
- なぜ悪い:片側スプレッド<手数料が常態。リベート無しだと期待値はほぼ負。
- 直し方:ゲーティッドMM(SpreadExcursion/反転時のみ)+時間帯/銘柄選別へ。実効メーカー≤2–3bpsまたは**別所(低fee/リベート)**で回す。
- ヘッジ前提の設計を持たず在庫に素で晒す
- なぜ悪い:トレンド局面でadverse選択に飲まれる。
- 直し方:先物/パーペでの瞬間ヘッジを想定(在庫上限を引き上げ、片翼撤退ルールを明示)。
- Queue位置/TTL/裏置き(1–2tick back)の初期設計不足
- なぜ悪い:BOB/BOAで同値競争→fillは悪いときにだけ付く。
- 直し方:TTL≒350–900ms・裏置きをαの強弱で切替、Queue滞留時間でサイズ/TTLを動的調整。
- 銘柄・時間帯の“勝てる窓”探索が後手
- なぜ悪い:板構造は時間帯/イベントでEVが大きく変動。
- 直し方:p80スプレッド・reject率・adverse中央値で運用窓を自動スケジュール。
2) 実装・順序の筋が悪い点
- “1本通す”単一路線(Canary)が序盤に常設されていない
- なぜ悪い:ACKもFillも無いと、以降の議論が全部抽象になる。
- 直し方:
/control: place_canary
をDay-0から常備(LIMIT_MAKER×遠値×最小notional)。
- ネット疎通(443)が塞がっているのに、Infraを先に磨いた
- なぜ悪い:外部APIに届かない限りEV検証に入れない。
- 直し方:最初の5分で
curl /time
→ 200。ダメなら別回線/Cloud VM/host networkに切替えて当日中に通す。
- Exporter二重構成/ログ体裁に過剰投資
- なぜ悪い:EVに直結しない。プロは監査OKの最小形に留めて次へ。
- 直し方:単一HTTPサーバ+**メトリクス監査(mm_control_actions_total, last_ts)**で十分。
- UserStream(fills)より先に周辺機能へ時間
- なぜ悪い:Fillが取れないとPnL分解が永遠に進まない。
- 直し方:ListenKey→WS接続を最初週の必達。接続生存Gauge(0/1)で監視。
3) 計測・KPIの筋が悪い点
- order_total の語義が“送信時”だった(ACK後じゃない)
- なぜ悪い:意志決定KPIが嘘になる。
- 直し方:
attempt / order(ACK) / reject
の三分離(修正済は◎)。
- 段別レイテンシとCancel RTTが後手
- なぜ悪い:どこで詰まっているか分からず闇雲に最適化。
- 直し方:
request→ack / cancel_rtt / total
を最初週で入れ、p50/p95/p99の“窓”を決める。
- PnL分解の器が遅い(fees/spread/slippage/adverse)
- なぜ悪い:EVが立っているかの判定ができない。
- 直し方:値は雑でも先に叩く。後で精度を上げる。
4) 運用・プロセスの筋が悪い点
- ビルド/ホットパッチが日々ブレる
- なぜ悪い:再現性が失われる。
- 直し方:その日どちらかに固定+
/metrics
にbuild_sha
を必ず露出。
- PYTHONPATH/実行モジュールのドリフト
- なぜ悪い:古いコードが動き続ける。
- 直し方:
mm_bot path=/app/mm_bot
のDay-0セルフチェックを追加。
- Secrets(APIキー)直書きの時期があった
- なぜ悪い:漏洩リスク→資金喪失。
- 直し方:ENV/Secretsで管理、
cfg_has_keys
だけをメトリクス露出。
- “完成理解”を求めてタスクを長く抱える
- なぜ悪い:学習サイクルが遅い。
- 直し方:Go/No-Goの受入を明文化し、通ったら即次へ(例:
p99/RPS 非NaN
→KPI3行
→Paper 24–48h
)。
5) プロの型:改善後の運用テンプレ(毎日90分の核)
- T+10m:Day-0セルフチェック(/control 200、runner attach、mm_bot path、base_url、
/time 200
) - T+20m:Canary 1本(ACKで
order_total +1
、段別ヒストに実サンプル) - T+20m:UserStream 接続(Gauge up、fill→fees/spread を加算)
- T+20m:Alert E2E(ダミーcritical→
disable_live
ログ+カウンタ) - 残り:SpreadExcursion gate と TTL撤退→24–48h Paperで EV>0/Fill≥35%/Reject≤3% を満たしたら最小Liveへ
6) 2週間の具体ロードマップ(再掲・短縮)
- Week 1:疎通→Canary→Fill→EV器(fees/spread)→AGMM(SpreadExcursion+TTL)
- Week 2:BRQ(反転クォート)+在庫スキュー→Paper→Go/No-Go→極小Live
最後に
厳しい言い方をすれば、**「稼げる土俵が整っていないのに、土俵の周り(Exporter/ログ体裁)を磨きすぎた」**のが今回の最大の筋悪です。
土俵=“EVが立つ条件”を先に満たす(手数料・時間帯・銘柄・ヘッジ/ゲーティング)→Canary/Fill/EVの三点セット→最小Live。
ここに軸を戻せば、開発速度と勝率は一段上がる。次の一報は 「ホスト /time
が200」 で。そこから一緒に“1本→EV”まで畳み切る。
CEX/CEX arb bot:開発サマリ
- 到達フェーズ:Phase 0「比較の正しさ Fix」最終段
- 技術達成度(システム完成度):85%
- “稼ぐ”達成度(収益化への到達度):40% ±5%(AUTO→GO=0%のため。ここが上がれば60%まで跳ね上がる見込み)
核心ブロッカー:
r = dq / cb = 0.802
が固定(≒ per-SOL 正規化が最終出力dq
まで貫通していない)contract_mismatch
未発火(r<0.90でもgross<min
に流れている)- ログの
diag
空(extra
→diag
への取り込み経路に欠落/別経路)
✅ 完了済み(強い土台)
- 命名統一:
fx_bp → fx_bps
、変数ゆらぎ解消。 - 統一出口
_emit
復活:落ちないデータ流し込み(EnhancedArbitrageData.from_any()
)を標準化。 - 価格正規化の契約定義:
jup_to_per_sol_usdt(tap, quote, fx)
実装・単体OK(BUY=100.2 / SELL=99.8)。- tap別で per-SOL 化(BUY:
in_usdc_total/out_sol_total
、SELL:out_usdc_total/in_sol_total
)。
- 符号・VWAP side の原則:
- BUY:
(CEX_BID − DEX_perSOL) / mid
、SELL:(DEX_perSOL − CEX_ASK) / mid
- BUYはBID、SELLはASKを使用。
- BUY:
- FSM/ログ/例外耐性:2-hit FSM、
from_any()
、一貫性チェッカー、詳細ログの器は整備済み。
❌ 未解決(現ブロッカー)
- r分布サニティ不合格:
r_p10=r_p90=0.8020
(固定) - 早期ガード未発火:
r<0.90
でもwhy=gross<min
に流れる - diagが空:
extra
がdiag
に反映されていない(ログでdiag={}
)
🔎 技術的診断(なぜ起きているか・疑い順)
H1. _emit
の詰め替え/上書き漏れ
_emit
内の詰め替えが 古い属性名を参照、またはその後でdata["dq"]=80.16
のように上書きしている疑い。- 手本:
data.setdefault("dq", getattr(q, "dq_per_sol_usdt", None)) data.setdefault("cb", getattr(q, "cb_per_sol_usdt", None)) data.setdefault("mid", getattr(q, "mid_usdt", None)) # 以降で dq/cb/mid を再代入しない
- 手本:
H2. 直帰ルートの混在(_create_opportunity_data 直呼び)
- 一部コードが
_emit()
を経由せず直接_create_opportunity_data()
を返しており、
per-SOL の詰め替えやdiag
取り込みを飛ばしている可能性。
H3. Jupiterモックのキーが契約とズレ
- BUYで
out_sol_total
ではなくamount_sol
など、期待キー名の不一致によりjup_to_per_sol_usdt()
が総額→per-SOLできていない。
H4. 早期ガードが “別分岐の手前/外側”
r
を計算しても、その直後に別条件でgross<min
を返す分岐が先に評価され、contract_mismatch
の return に到達していない。
H5. diag
取り込み欠落
_emit
内でdata.setdefault("diag", {})
をせず、data["diag"].update(extra)
だけだと未初期化で無効になり得る。- 手本:
if extra: data.setdefault("diag", {}) data["diag"].update(extra)
- 手本:
🧪 即時チェック(3分・ノブは触らない)
- dq/cb/mid の最終詰め替えが per-SOL 名になっているか
grep -n 'setdefault("dq"' arbbot/strategy/enhanced_arbitrage_detector.py grep -n 'setdefault("cb"' arbbot/strategy/enhanced_arbitrage_detector.py grep -n 'setdefault("mid"' arbbot/strategy/enhanced_arbitrage_detector.py
→dq_per_sol_usdt / cb_per_sol_usdt / mid_usdt
を参照していること。
→ 直後にdata["dq"]=...
の上書きが無いこと。 - 直帰ルートの掃除
grep -n '_create_opportunity_data\(' arbbot/strategy/enhanced_arbitrage_detector.py
→ 全呼び出しが_emit()
経由になっていること(直呼びはゼロが正解)。 - 契約ガードの実在と位置
grep -n 'contract_mismatch' arbbot/strategy/enhanced_arbitrage_detector.py
→r = dq_per_sol_usdt / cb_per_sol_usdt
の直後にif r < 0.90 or r > 1.10: return self._emit("contract_mismatch", tap=tap, sym=sym, extra={"r": r, "jup_contract": contract, **jdiag})
があること。 - diag 初期化
grep -n 'diag' arbbot/strategy/enhanced_arbitrage_detector.py | head
→_emit
内でdata.setdefault("diag", {})
→update(extra)
の順になっていること。 - モック契約のキー名
- BUY:
in_usdc_total
/out_sol_total
- SELL:
out_usdc_total
/in_sol_total
→ これ以外(amount_sol
など)なら生成側で上記キーにコピー。
- BUY:
📈 現在KPI(最新)
- AUTO→GO:0%(目標 ≥30%)
- WHYトップ:
gross<min
100% - unit_mismatch:0%(目標 ≤3%)
- miss_2nd:0件(未到達のため。gross解消後に評価)
- r分布:
p10=p90=0.8020
(不合格)
🎯 次の一手(コード1点だけ)
_emit
の dq/cb/mid 詰め替えとdiag初期化を、上記の「あるべき姿」に統一。detect_opportunity
内でcontract_mismatch
ガードを r 計算直後に配置。_create_opportunity_data
の直呼び撤去(全件_emit
経由に戻す)。- Jupiterモックのキー名を契約どおりに揃える(BUY: in+out、SELL: out+in)。
これで r が ±1% に収束し、
gross<min 全件
が解消 → AUTO→GO 立ち上がりに入れます。
✅ 受け入れ基準(この順で通過)
- r分布合格:
r_p10 ≥ 0.99 & r_p90 ≤ 1.01
- 45分ラン(USオープン±30):
AUTO→GO ≥ 30%
、WHYにdepth/last_look/miss_2nd
が現れる - canary最小ロット×5本:
GO→FILL ≥ 60%
&realized_edge_p50 ≥ fees+slip_p75
📒 Run Manifest(再現性)
各ランで保存:
{ "ts":"<iso>", "git":"<sha>", "env":{"NET_EDGE_MIN_BPS":38,"TTL_SECONDS":3.0,"SECOND_WINDOW_MS":1500,"VWAP_MAX_AGE_MS":250}, "tap":["buy->sell"], "dex_norm":"per-SOL(total→/qty)", "vwap_side":{"buy":"BID","sell":"ASK"}, "slip":{"buy":"+","sell":"-"}, "r_stats":{"p10":0.XXX,"p90":1.XXX}, "why_top":"gross<min|depth|last_look|miss_2nd", "auto_go":0.XX }
ひとこと
土台は十分強い。 いま止まっているのは “per-SOLが最終 dq
に届いていない”ただ一点。
上のチェック&1点修正で r
は即合格圏に入ります。
CEX/DEX arb bot開発:筋悪ポイント&改善案
1) モック・ドリフト(Mock ≠ 本番)に時間を溶かした
症状:r=0.802 固定、gross<min
全件。Jupiter契約/単位の齟齬を何度も後追い修正。
なぜ悪い:本番の契約(総額→per-SOL、decimals、slip向き)に厳密準拠しないモックは“別ゲーム”。そこに合わせ込むほど実運用から離れる。
Fix(次ループ):
- “契約→正規化→エッジ”のゴールデンテストを先頭に置く:
BUY:in_usdc_total/out_sol_total * fx == dq_per_sol_usdt
、SELL:out_usdc_total/in_sol_total * fx == dq_per_sol_usdt
をCIで落とす。 - モックはMarketBaselineの単一baseをCEX/DEXで共有、slip向き(BUY:+/SELL:−)だけ可変。これ以外の挙動は禁止。
2) 早期不変量を“ゲート”にせず、後段で調整した
症状:r分布不合格のままTTL/SECOND_WINDOW/NET_EDGEなどを触りがち。
なぜ悪い:比較が間違っている状態でタイミングや閾値を調整しても因果が崩れる。
Fix:ゲート順を固定
r=dq/cb
±1% 合格(BUY=BID/SELL=ASK/符号/FX一回)AUTO→GO≥30%
(ここで初めてTTL/SECOND_WINDOWを触る)- GO→FILL(canaryで実滑り確認)
3) 多ノブ同時調整
症状:TTL/SECOND_WINDOW/NET_EDGE/VWAP間隔/slippageを並行で変更。
なぜ悪い:効果検証が不可能になり、再現もできない。
Fix:45分=1ノブ。Run Manifestに1行で「変更ノブ→予想→結果」を残す。
4) 統一出口を外してデータが壊れた
症状:_emit
を外して _create_opportunity_data
直呼び → diag
空、必須フィールド不足、dq
が総額に戻る。
なぜ悪い:観測の一貫性が消え、“どこで壊れたか”が追えない。
Fix:全ルート _emit()
経由に統一(中で from_any()
、diag.setdefault({})
、dq/cb/mid=per-SOL
詰め替え)。
5) tap非対称(BUY→SELLだけ)で検証が偏った
症状:dex_buy_cex_sell
片側中心、SELL側ASK/符号の回帰テスト不足。
なぜ悪い:半分のバグ(符号・side・slip向き)が露見しない。
Fix:両tapの不変量テストをCIに追加(BUY: BID−DEX
、SELL: DEX−ASK
)。
6) NET_EDGEを先に緩めた
症状:38→35bpsなどの調整を“比較未合格”の段階で検討。
なぜ悪い:ノイズを拾い、負けトレードが混入。
Fix:閾値は最後。まず“正しい比較”と“AUTO→GO立ち上げ”。
7) 動的調整を早期導入
症状:DynamicAdjusterを“基礎が揺れている”段階で動かそうとした。
なぜ悪い:誤ったフィードバックで発散する。
Fix:動的調整は安定後(Step-B以降)の微分だけに使用。
8) 収益化視点の“面取り”が遅い(戦略選定)
症状:SOL/USDTの常時CEX/DEX裁定に固執。
なぜ悪い:2025年のメジャー銘柄常時裁定はHFTの土俵。個人が勝てるのは“短時間×ニッチ”。
Fix(戦略):
- 時間帯×銘柄の細分化:USオープン±30/ルート再計算直後/薄板アルト。
- イベント駆動の瞬間エッジ:Jupiterのルート更新・プール再均衡・CEXメンテ明け。
- サイズ固定の薄取り:$10-$25のVWAPに合わせたマイクロロット多数回。
- 両面化:CEX maker(手数料優遇)× DEX taker など、費用構造に依存した組み合わせを試験。
- 銘柄横断のαマップ:
(spread_raw – fees – slip_p75)
のp50を銘柄×時間帯ヒートマップで可視化→“勝てる面”に集中。
9) 実弾 canary が遅い
症状:モックで長く滞留。
なぜ悪い:実世界の滑り/約定/キュー待ちをログで体感しないと、いつまでも机上。
Fix:最小ロット×5本をUSオープン±30で毎日。pred/quoted/realized_edge_bps
を同一行に出す。
10) 事前サニティの自動化不足
症状:r分布合格・契約ガード・VWAP side一致を毎回手で見る。
なぜ悪い:人的ミスが出る。
Fix:プリフライトで落とす
r_p10>=0.99 && r_p90<=1.01
でない→即Fail- BUYで
vwap_side=BID
/ SELLでASK
でない→即Fail diag.jup_contract ∈ {buy_total, sell_total}
でない→即Fail
戦術→明日の動き(筋の良い回し方)
- r分布を必ず合格(_emit詰め替え・直帰撤去・契約ガードの位置を修正)
- 合格まで他ノブ禁止。
- 45分=1ノブで
AUTO→GO≥30%
を立ち上げ- WHY=depth → VWAP間隔 100→80ms(CEXのみ)
- WHY=last_look → age上限 250→200ms
- WHY=miss_2nd → プリフェッチ(それでもp95>2000msなら窓+200ms)
- canary最小ロット×5本で
GO→FILL≥60%
とrealized_edge_p50 ≥ fees+slip_p75
を確認 - 面の拡張:tap両側・もう1銘柄・時間帯横展開(αマップで決定)
まとめ
- 技術土台は強い。
- 筋が悪かったのは:モック最適化・多ノブ同時・不変量をゲートにしなかった点。
- やることは単純:契約→正規化→r合格→1ノブ→canary。
ここを守れば、AUTO→GO 0% → 30%台は届く。その先で戦略選定(ニッチ×時間帯×サイズ)にリソースを回せば、“個人が勝てる面”に乗れる。
ショート系bot開発:進捗サマリー
- 計測・基盤:multiprocess集約と
/metrics
サーバは復旧。EVは Summary一本化(short_ev_bps_(sum|count)
)に移行済み。 - EV配線:Δ(WS/REST)→ 注文終端(
FILLED/EXPIRED/CANCELED
)で VWAP→EV算出まで動作。ネットEV(taker手数料控除)も導入済み。 - 執行:
req→ack ≈ 10–11 ms
、reject=0、CB=0。 - FFL/スモーク:FFLは3/6 fill(50%)まで改善した回あり。ただし 10分スモークは 1/60〜39/136 と ばらつき大。
- EV実測:
raw_ev_bp ≈ +0.034
(=0.034 bps)だが 手数料7.5 bps控除後は ≈ −7.47 bps → ネットでマイナス。 - 前段ゲート:L2流動性ゲート(cum bid ≥ qty)は導入。マイクロ構造ゲートは一時OFF(L2モックが対称で信号0のため)。
いま“できている / 良い”ところ
- EVの単位・定義が是正(Summary、bps、ネット控除)
- 注文ライフサイクルの観測:ACK/DONEログ、
short_orders_done_total{status}
- L2健全性ログ:IOC直前に K枚の集計・microprice・age・src を出力
- FFLルーチン:セッション冒頭の「Market1→IOC×5→3指標」導入
不可解/筋の悪い点(Must-fix)
- Fill率の分母が歪む
ioc_timeout_total=0
でも fillが低い回があるのに、EXPIRED(0fill) が分母に入っていない瞬間がある。- 現状
short_skip_total{reason="no_qty"}
(=置く前スキップ)と、「置いたが約定0でEXPIRED」 が混同されている。
対処:short_expires_nofill_total
を DONE時(executed=0)で必ずinc。Fill率はfills / (fills + expires_nofill + rejects)
に統一。
- L2モックが対称(sum_bidK=sum_askK=1.000固定)
- その限り、imbalance/micropriceは常時0付近 → マイクロ構造ゲートが機能しない。
対処:Testnet実板 or 変動を持つシムへ切替えるまで マイクロゲートはOFF継続。L2ゲート(cum量)だけで運用。
- その限り、imbalance/micropriceは常時0付近 → マイクロ構造ゲートが機能しない。
- EV期待値の目標設定
- ネットで +3 bps を狙うには raw_ev_bp ≳ 10.5 bps が必要(手数料7.5 bps控除を踏まえる)。
- 現状 raw ≈ 0.034 bps → 桁が足りない。
対処:“置く前に勝てる瞬間だけ撃つ”密度をさらに上げる(下の次アクション)。
- /metrics が空になる瞬間がある
PROMETHEUS_MULTIPROC_DIR
の未設定起動、epoch張替え直後に子が別DIR参照、で空になり得る。
対処:親子とも import前にENV設定、epoch張替えはos.replace()
の原子的置換、janitorは古い.db
のみ掃除。
次の一手(30–60分でやること)
目的:Fill率の“真値化”+ 置く前の勝率を底上げ → ネットEVの赤字幅を縮小。
- メトリクスの締め
- ✅
short_expires_nofill_total{mode,symbol}
(DONEで executed=0 のときinc) - ダッシュの Fill率を
fills / (fills+expires_nofill+rejects)
に差し替え。
- ✅
- 前段ゲートの再調整(シンプルに2本)
- L2流動性ゲート:
cum_bid(sell_price) ≥ 1.0 × qty
(まずは 1.0 に緩和、統計が安定したら 1.2 に戻す) - クロス幅:初手2tick固定 → 直近30本の timeout率で
2↔1tick
自動切替(>30%で2、<10%で1)
- L2流動性ゲート:
- サイズのゼロ化を撲滅
qty_from_notional
の safety係数=1.01 を維持、ログにcalc_qty / step / min_qty / min_notional
を毎回出す。skip{reason="no_qty"}
とexpires_nofill
は別モノとして並列で追跡。
- 10分スモーク再測定(Go/No-Goゲート厳守)
- Go:
fills/(fills+expires_nofill+rejects) ≥ 0.5
&avgEV_net > +3 bps
&timeout/orders < 0.1
- No-Goなら:
- Fill率<0.5 → cross=2tick継続+L2しきい値を 1.0→0.9 に一時緩和
- avgEV_net≤0 → cooldown導入(連続負けで
3×interval
休止)
- Go:
- 記録の型を固定(レビュ映え&再現性)
- 4本スナップに
expires_nofill
を追加。 - FFL結果(fills>0 / ev_count>0 / staleness≤300ms)を毎セッション先頭に保存。
- 4本スナップに
48–72時間の見取り図(個人でも勝ち筋を太くするために)
- Phase 1(〜明日):上の 1)〜4) を回し、Fill≥50% を安定させる。
- Phase 2(明後日〜):L2が“生きた”データ源に切り替わり次第、マイクロ構造ゲートを段階導入
- 最初は sell_flow_ratio_200ms > 0.60 の単独ゲートから(逆行回避に効く)。
- 次に imbalanceK、microprice を加えて AND にする(誤発注をさらに削る)。
- Phase 3:EV完全体の拡張(Funding/借入)+ 時間帯/レジームON/OFF。
- 例:高ボラ・イベント直後はOFF/縮小、定常帯に集中。
- Phase 4:AB常時(
mode="cross1" vs "cross2"
)で7日ローリングの勝ち腕選択。
ひと言でいうと
- Fillの“分母”を正しく計る → 置く前ゲートで“負ける瞬間”をさらに間引く → net EVをマイナスからゼロ近辺へ引き上げる、の順で進めば、24h Canaryへ進む意味のある手応えが出る。
- いまの raw EV(0.034 bps)は桁不足なので、撃つ瞬間の質を上げる以外の近道はない。
ショート系bot:筋悪ポイント&改善提案
結論から言うと、「1–2tickのIOC Takerで勝つ」前提に時間を使い過ぎ、しかも**“勝てる瞬間だけ撃つ”ためのアルファ設計が後手**になっていました。筋が悪かったポイントは次のとおりです。
戦略選定(根本)
- Taker1–2tick狙いはネットで負ける前提
実測の raw EV ≈ +0.034 bps、taker手数料 7.5 bps → ネット ≈ −7.47 bps。
なぜ悪い:構造的に手数料に負ける。ミクロな優位(イベント/板構造/他会場遅延など)が乗らない限り永遠に赤字。
直し方:Takerは**“何で勝つか”を先に定義**(例:清算/イベント直後、他会場スリッページ伝播、特定時間帯のフロー偏り)。それが言語化できないTakerは切る。短期はメイカー混成か軽い裁定合成(先物-現物/他板のミクロ乖離)に軸足。 - アルファよりインフラ先行
Prometheusやmp集約に多くの時間→fillすら出ない期間が長い。
直し方:FFL(Market1→IOC×5→指標3点)を毎セッション冒頭で完了しない限り、他作業に行かない“開発ゲート”にする。 - モック依存でミクロ構造ゲートが“常時0”
L2が対称(sum_bidK=sum_askK)→ imbalance/micropriceが常に0→ゲートが機能しない。
直し方:Smoke/CanaryはTestnet実板のみ。モックは単体テスト専用に降格。
実装・計測
- EVの単位/定義の取り違え
0.034を「3.4 bps」と読んだり、SummaryとCounterを二重定義。
直し方:bpsで一本化、EVはSummary1本(_sum/_count
)。**ネットEV(手数料控除後)**を標準に。 - Fill率の分母が歪む
timeout=0%
でもfillが低い回→EXPIRED(0fill)をカウントしていない。
直し方:expires_nofill_total
をDONE時に必ずinc。Fill率定義=fills/(fills+expires_nofill+rejects)
に固定。 - “待てば刺さる”誤解
IOCは即判定。待機を伸ばしても約定率は上がらない。
直し方:待機は報告収束のためだけ。約定率は撃つ前の条件で上げる(次項)。 - 前段ゲートの弱さ/後付け
置く前の勝率を上げるゲート(L2累積・マイクロ構造・フロー)が遅れた。
直し方:最低でもL2累積(sellまでのbid量 ≥ qty)+クロス幅自動化を常時ON。ミクロ信号は実板で復帰。 - p_ref・orderIdの一貫性崩れ
p_refの取り直し、orderId不一致、Decimal/float混在、price=0.001
バグ…基礎品質にノイズ。
直し方:注文ID→p_ref固定→送信→受領IDに束縛の順をテストで固定。Decimal一気通貫を徹底。
プロセス・運用
- Smoke不合格なのにCanaryへ進む
露出が先行して学習効率が下がる。
直し方:数値ゲート厳守(fills≥50%
かつavgEV_net>+3bps
ほか)未達は進まない。 - リスク上限が口約束
日次コスト/露出上限の自動停止が曖昧。
直し方:日次bps予算を固定(例 −X bps or −$Y)&自動disable_live
。再入場はレビュー後。
いまからの修正方針(現実解によせて)
- 戦略ミックスを見直す
- テイカーはイベント/清算/遅延伝播など構造的優位が説明できる場面に限定。
- 日中の定常帯はメイカー(狭い両建て+在庫管理)や軽い裁定でベースの+3〜5 bpsを作る。
- 撃つ前の品質を最大化
- L2累積ゲート(≥1.0〜1.2×qty)+**クロス幅自動化(2↔1tick)**常時ON。
- 実板が取れ次第、sell_flow比率→imbalance→micropriceの順で段階導入(ANDゲート)。
- 定量ゲートを最上位の意思決定に
- Smoke Go:
fills/(fills+expires+rejects)≥0.5
&avgEV_net>+3bps
。未達なら即チューニング、進まない。 - Canary Go(24h):
avgEV_net>+2〜3bps
維持+SLOクリア。
- Smoke Go:
- AB常時・人力チューニング禁止
mode=cross1(1tick)
vscross2(2tick)
を並走。7日ローリングで勝ち腕のみ残す。
1週間ロードマップ(短く太い勝ち筋へ)
- Day 1–2:L2累積ゲートとクロス自動化を常時ON、Fill率を**50%**に安定。
- Day 3–4:実板でsell_flow>0.6をゲート化 →
avgEV_net
の符号がゼロ超えに乗るか確認。 - Day 5–7:時間帯/レジームON/OFF(高ボラ・イベント直後はOFF)。並行してメイカー/裁定の最小腕を追加し、ベースEVを底上げ。
まとめ
- 最大の筋悪は、「手数料に勝てないテイカーでインフラを磨き続けた」こと。
- 勝ち筋は、「撃つ瞬間の質を前段ゲートで上げる」「構造的エッジが説明できる場面に限定」「メイカー/裁定混成でベースbpsを稼ぐ」。
- これに数値ゲートの厳守とAB常時を重ねれば、個人でも**+3〜5 bps ネット**の現実路線が見える。
オンチェーン清算スナイプbot:開発進捗
🎯 目標(今日~直近)
- **Round-1(実データ)**を完了:
KEEP ≥ 60%(連続2ラウンド)/p95 ≤ 350ms/EV/5m > 0 → 採用
採用後:fill_drop ≤ 10%(60分連続)
✅ できていること(緑)
- Exporter:
:9106/metrics
常駐、EV(gain/loss)/REPLAY info/knob_current/invar/req_ack_ms 出力確認済み - Registry:
get_registry()
に統一(重複/default REGISTRY混在の是正) - Dev Prometheus:別ポート(:9094) で並走起動、
sniper-local
UP(既存:9090を汚さず運用) - 供給検証:8分供給で
p95
正常算出(rate([5m])満足) - フロー:擬似データでRound-1配線(1クリック→A/B→有意性→EVゲート)正常
- 運用基盤:A/B(ブロック5分交互)/二相探索(粗→細)/EV採用ゲート(
SIGNIF ∧ EV/5m>0
)
🟨 進行中(黄→緑に持ち込み可能)
- Recording Rules:一部 YAML 構文エラー→分割(
rules_*.yaml
/alerts_*.yaml
)で運用可 - fill_drop:NaN(原因:ルール未定義/未読込 or exporterでGaugeを作ってしまった)→ルール算出に戻す
🟥 未了(赤)
- 実アプリ本体(shadow):安定稼働に未達(起動経路の確定、
:9106
一本化) - Round-1(実データ):未完(直前のスクレイプ/ルール調整待ち)
🔍 不可解/危険ポイント(原因→処方箋)
- Prometheusが :9106 をスクレイプしていない
→ 既存:9090はR/O。:9094 を別起動しsniper-local
を登録(実施済)。
チェック:curl :9094/api/v1/targets
でhealth:"up"
。 - Recording Rulesの構文エラー
→monitoring/final_monitoring_rules.yaml
のline 72付近。
処方:ルールをrules_*.yaml
/alerts_*.yaml
に分割しpromtool check rules
→/-/reload
。 - fill_drop をGaugeで出力している(NG)
→ 正しくは Recording Rules で算出。
処方:exporter側のhl_fill_drop_5m
を撤去、以下を :9094 にロード:参照yamlファイルは別途掲載。 - PromQLの集計軸が不正
→histogram_quantile(... rate(bucket[5m]))
は空になりがち。
正:sum by (le) (rate(..._bucket[5m]))
(銘柄別はsum by (le,symbol)
)。
供給:6〜8分 は流す(scrape 5s 前提)。 - Exporterの多重化(
:9106
と--prometheus-port 8001
併存)
→ :9106 一本化、CLI側 exporter は一旦OFF。start_http_server(9106, registry=get_registry())
。
以下は、3のyamlファイル。※ live/shadow_*
の ラベル集合(symbol/side/reg)を一致させること。
groups: - name: hl-drop interval: 15s rules: - record: hl:exec_drop_5m expr: clamp_min(1 - (sum(increase(live_exec_attempt_total[5m])) / clamp_min(sum(increase(shadow_exec_attempt_total[5m])), 1)), 0) - record: hl:fill_drop_5m expr: clamp_min(1 - (sum(increase(live_fill_success_total[5m])) / clamp_min(sum(increase(shadow_fill_success_total[5m])), 1)), 0) - record: hl:fill_drop_5m_by_symbol expr: clamp_min(1 - (sum by(symbol)(increase(live_fill_success_total[5m])) / clamp_min(sum by(symbol)(increase(shadow_fill_success_total[5m])), 1)), 0)
🛠 直ちにやること(15–30分)
- ①ルール分割→検証→リロード
promtool check rules monitoring/*.yaml curl -X POST http://127.0.0.1:9094/-/reload
promtool check rules monitoring/*.yaml curl -X POST http://127.0.0.1:9094/-/reload
- ②fill_drop をルールへ移行(上記 rules を追加)
- ③8分供給→プレフライト
export PURL=http://127.0.0.1:9094/api/v1/query PYTHONPATH="/Users/xxx/Hyperliquid Sniper" \ PROMETHEUS_MULTIPROC_DIR=/tmp/sniper_mp/current \ python -u scripts/sim_feed_metrics.py & ./scripts/120s_preflight.sh
- ③検証クエリ(NaNが消えたか)
curl -s :9094/api/v1/query --data-urlencode \ 'query=histogram_quantile(0.95, sum by (le) (rate(mm_total_latency_ms_bucket[5m])))' curl -s :9094/api/v1/query --data-urlencode 'query=hl:keep_rate_5m_fallback' curl -s :9094/api/v1/query --data-urlencode 'query=hl:fill_drop_5m'
🚀 次の一手(実データ Round-1)
前提:p95 / keep / fill_drop
が非NaN
- 実アプリ shadow 起動→2分待機
:参照コードは下部に記載。
- 攻め順決定→1クリック(段階A)
./scripts/ltk_attack_decision.sh
(不足時は{"knob":"OI_Z","direction":"down","step":0.1}
を暫定)./scripts/one_click_evaluation.sh ...
(5分A/B→CSV)
- 採用判定(EVゲート)
- 採用:
SIGNIF ∧ PASS+SIGNIF ∧ (hl:ev5m > 0)
- NS/DEFER:10分窓 or
MIN_DENOM↑
(300–500) - FAIL:
rollback
→段階B(L2_THIN↑
orBURST↓
の片方のみ)
- 採用:
- 採用後:drop常設 → Canary最小ノッチON(25USD)
- 60分
hl:fill_drop_5m ≤ 0.10
を監視(銘柄別hl:fill_drop_5m_by_symbol
を併読)
- 60分
PYTHONPATH="/Users/xxx/Hyperliquid Sniper:$PYTHONPATH" \ PROMETHEUS_MULTIPROC_DIR=/tmp/sniper_mp/current \ python -m src.hyperliquid_sniper.cli trade --mode shadow --enable-metrics --log-level INFO &
📈 KPI & マイルストーン(24h目標)
- KEEP ≥ 60% …… 連続2ラウンド
- p95 ≤ 350ms …… 維持
- EV/5m > 0 …… 2ラウンド連続 → 採用
- fill_drop ≤ 10% …… 60分連続(全体&ワースト銘柄)
📊 進捗率(現時点の見立て)
- 基盤構築:100%
- モニタリング(ルール):90%
- 擬似データ検証:100%
- 実アプリ稼働:30%(shadow起動経路の安定化が残り)
- Round-1(実データ):0% → 本タスクで着手可
- 総合達成度(“稼ぐ”まで):約75%
🧭 この後ほしい出力(貼れば即 次ノブ指名)
curl -s :9094/api/v1/targets | jq '.data.activeTargets[] | {job,url:.scrapeUrl,health:.health}'
./scripts/120s_preflight.sh
の結果(OK/NGのみで可)- 2行ヘルス(直近ラウンド)+ CSV最新1行 + drop内訳Top3
一言まとめ
根本(:9106未スクレイプ)は回避済み。 残りは ルール整備と集計軸を直してNaN→実値にすれば、そのまま実データ Round-1に入れる。ここまでの積み上げは十分。あとは1クリック→A/B→EVで採否に集中する。
清算スナイプ:筋悪ポイント&改善提案
P0|直ちにP/Lを殺す類(戦略×実装の根っこ)
- エッジ不在のままインフラ先行(Infra ≫ Edge)
- Why: Prom/Exporter/ダッシュは強いのに、“何で勝つか”の仮説→検証→縮小実弾が後手。学習データ(実 fill/失敗)が貯まらず最適化が空回り。
- Fix Now: EV先行に完全転換。採用条件=
SIGNIF ∧ EV/5m>0
を厳守。今日の実データRound-1を影→最小canaryで必ず通す(たとえKPIが荒くても)。
- 清算スナイプの“勝ち筋”を楽観視(個人の比較優位を外している)
- Why: 清算は待ち時間×同着勝負×PO/queue細工の競技。個人で継続して抜くにはキュー最適化/市場条件選別など“味付け”が必須。
- Fix Now: 銘柄×時間帯×状態で出る所だけ撃つ。
queue_position_estimate
/post_only_removed_total
/nofill{reason}
をKPI化し、USオープン±など好条件だけONにする“状態ゲート”を即導入。
- プロキシKPI偏重(KEEP・p95)で“お金KPI(EV)”が後段
- Why: KEEP↑でも負ける戦略は普通にある。採用判定を間違えると最速で負ける。
- Fix Now: ダッシュの一等地に**
hl:ev5m = rate(gain)-rate(loss)
を常設。EV>0でない改善は採用しない**。
- 本番データより“擬似/手作りメトリクス”で配線を通しがち
- Why: Gaugeで
fill_drop_5m
を作る等は観測バイアスを生む。PromQLで落ちる原因(scrape/集計軸/供給長)を隠蔽。 - Fix Now: すべてRecording Ruleで算出(exec/fill drop、p95)。exporterは生イベントのみ。擬似は“窓を満たすために流すだけ”。
- Prometheus/registryまわりの迷走(学習時間の損失)
- Why: :9106未スクレイプ、default REGISTRY混在、
*_bucket
直定義…観測不能期間が長い=学習ゼロ。 - Fix Now: :9094 dev Prom + rules分割 +
registry=get_registry()
統一 + 6–8分供給を固定フロー化。もう壊さない。
P1|稼ぐ速度を落とす設計ミス
- パラメータ探索が線形(1クリック一本槍)
- Why: KEEP48→60%帯での線形探索は遅い。
- Fix Now: 二相探索(粗:倍々で閾値跨ぎ→細:±1クリック)。
d_keep_per_step
大のノブから。
- A/Bが時間連続の偏りに弱い
- Why: 状態変動(流動性/ボラ/板厚)でSimpson’s paradox。
- Fix Now: ブロック型(交互5分)or 状態層化A/B。採否は全体+層別の両方で。
- 分母ブレ(shadow/liveの条件不一致)
- Why: attemptの定義/ラベル不整合でdrop評価が歪む。
- Fix Now: attempt定義をsend直前に統一。
symbol/side/reg
ラベル集合を完全一致させ、parityアラート(Warn10%/Recover5%)で監視。
- ALIGN張り付きの盲点
- Why: E2E p95がきれいでも、
req→ack
/ack→fill
の悪化で負ける。 - Fix Now: SLO/アラートは素RTT/ttfベースも必須。退行判定は素系優先。
P2|中期で効く戦略・運用の見直し
- 戦略の目利きが“平均的”
- Why: 清算は人多すぎ×賞金一定。個人は“出現帯/相場相”の選球眼で勝つゲーム。
- Fix: 3本柱で分散:
- 清算スナイプ(絞り撃ち):銘柄×時間×状態ゲート+queue/PO最適化
- FR/資金フロー系:Funding逆張り・定時イベントでの保守的EV回収
- スプレッド/MM系(低速):リスク小・EV/$良好の銘柄だけで小回し
- 採用後の回帰確認がない
- Why: 一発当たり→翌時間帯で死ぬ典型。
- Fix: 採用後T+60分で自動回帰A/B。退行なら自動ロールバック。
- 撤退ライン不明
- Why: ズルズル続けてチャンスコスト増大。
- Fix: Kill基準明文化:
- 2週間で KEEP<60 or fill_drop>15% 持続 → 方針転換
- 4週間で 稼働日のEV>0が50%未満 → 縮小/ピボット
直近7日アクション(これだけでP/Lの針が動く)
Day1–2:ルール整備→NaN撲滅→実データRound-1
- rules分割・
hl:fill_drop_5m
導入・供給8分→p95/keep/drop
非NaN→shadowでRound-1→EVゲート採否
Day3–4:二相探索+ブロックA/B
OI_Z
/BBO
を粗→細で。SIGNIF ∧ EV>0のみ採用。parity/素RTT/ttfを併読。
Day5:queue/POの数値化&是正
queue_position_estimate
/post_only_removed_total
/nofill{reason}
で原因→対処を日次で回す。
Day6–7:時間帯プリセット&状態ゲート
- USセッション±でFIRE緩め、悪条件帯は撃たない。
- 採用後のT+60分 回帰A/Bを自動化。
戦略選定について
- 清算一本足は“当てる瞬間の派手さ”とは裏腹に継続難易度は高い。個人で年中抜き続けるには
① 場を選ぶ(銘柄×時間×状態)、
② queue/POの地味な最適化、
③ EV/$視点でのスケール戦略
が要る。 - 分散軸を早めに持つ(FR/低速MM/イベント系)ほど、学習速度と生存率が上がる。全てを清算で賄おうとすると学習が“当たり待ち”になりがち。
最後に
- Infra/観測:◎(個人として希少レベル)
- “勝ち筋”への資源配分:△(EV採用の徹底・二相探索・状態ゲートで改善余地大)
- 戦略ポートフォリオ:△(清算に寄り過ぎ。FR/低速MMを少量でも並走推奨)
ガンマスキャルピングbot:開発サマリ
- 目的:イベント窓(JST 22:15–23:00 等)に限定したガンマ・スキャルピングMVPで「まず$1」を安定して取りにいく。
- 状態:実運用レベル(約95%)。MVP・多層ガード・WS統合・安全停止・アンワインド・Runbook・失敗ドリルまで整備済み。
- 残り: “スキマ潰し”の最小パッチを当て、イベント窓の自動運転(scheduler)+軽量オートチューンで再現性を底上げ。
✅ 実装完了(コード/運用)
コア機能
- Bybit V5 REST/WS クライアント(署名・リトライ・WS再接続)
- ATMストラドル建て → Δヘッジ(Perp BTCUSDT / Market-IOC / orderLinkId必須)
- 数量量子化(
lotSizeFilter
準拠、ゼロ落ちはminOrderQty
へ引上げ) - PnLブック(在庫ベース、部分約定VWAP対応、WS実fill利用)
- ログ(CSV+セッションID+パラメタスナップショット+
theta_tick/accum
)
安全・安定化
- 多層ガード:スプレッド・ステイル・クールダウン・ノーション上限・可変スリープ
- 利確/損切:
PNL_TARGET_USDT
/STOP_LOSS_USDT
(+1 / -3 既定) - ヒステリシス:
DELTA_FIRE
/DELTA_CLEAR
- 安全停止:SIGINT/SIGTERM →
safe_unwind_linear()
→shutdown_complete
- 完全アンワインド:線形に加え オプション
reduceOnly IOC
(建付け最小ロット分をfinallyでクローズ) - WS:
greeks
/execution.linear
/order.linear
(キャンセル即確定)
運用スクリプト
tools/setup_logs.sh
:セッション別CSV自動発行scripts/run_session.sh
:プレフライト→本番→解析(鍵チェックあり)scripts/param_tweaks.sh
:fire_up/down
/refr_up/down
/guard_up/down
/show_env
scripts/failure_drill.sh
:WS/RESTフォールバック・429/5xx耐性・スプレッド急拡大・θブロックtools/summarize_log.py
:hedges / realized / realized_net / delta p95 / skips / theta_accum / time_to_exit
⚠️ 不可解な点/リスク(開発過程で洗い出し)
- CSVスキーマ漂流:イベントごとにキーが不同 → 解析で列ズレ
- WSキュー肥大/取り違え:無限キューや並列化で他注文のfillを誤消費する余地
- IOC空振り確定:
order.linear
のCancelled/Rejected
を必ず拾う版か要確認 - mid/スプレッド計算:
bid/ask
欠損時のゼロ割・NaN - ノーション上限:ヒット時に在庫が残る可能性(breakだけ)
- 時計ズレ:
retCode=10006
を防ぐための skew 可視化(±1.5s超は注意) - .gitignore:
logs/*.csv
/.env*
の誤コミット対策 - Θ単位の明示:
theta_accum
の単位(per_day/per_hour)をログに一緒に出す
これらは最小パッチで解消可。既に多くは適用済み or すぐ当てられる状態。
🩹 すぐ効く最小パッチ(合意事項)
- ロガー:
DictWriter
で列固定+未知キーはnote(JSON)
に格納(スキーマ漂流防止)。 - WSキュー:
maxsize
付与+QueueFull
時は最古drop(リーク/遅延抑止)。 - orderキャンセル:
order.linear
を同一キューに流し、await_fill_or_done()
で即確定。 - mid/スプレッド防御:
bid/ask
欠損時はmid=ref_px
、spread_bps=0
で安全化。 - ノーション上限:ヒット即
safe_unwind_linear()
実行。 - プレフライト:
/v5/market/time
でskew表示(±1500ms超なら警告)。 - .gitignore:
logs/
,.env*
,__pycache__/
,*.pyc
を明示。 - ログ:
theta_accum
行にunit=per_day|per_hour
を追加。
🛠 いま回す(30分)チェックリスト
- ENV/依存:
source env.example
→export BYBIT_API_KEY/SECRET
→poetry install
- プレフライト:3行OK+
server-time skew(ms)
が±1500ms以内 - DRY_RUN:
./scripts/run_session.sh
(配線OK) - 本番小口:同コマンド(時間窓=22:15–23:00推奨)
- 解析:
python tools/summarize_log.py "$GAMMA_LOG_FILE"
- 合格ライン:
exit=take_profit_exit
/hedges=8–15
/delta p95
が帯内 /realized_net ≥ 0
- 合格ライン:
- “つまみ”1段だけ:
- 例)ヘッジ過多 →
fire_up
(+0.002)+refr_up
(+0.2s) - 取り漏れ感 →
fire_down
(-0.002)+guard_up
(+2bps) - spreadスキップ多 →
guard_up
(+2bps)or 時間帯変更 - θ重い →
TIME_WINDOW
短縮 orTHETA_BUDGET
厳格化(+0.2/h)
- 例)ヘッジ過多 →
📅 直近スプリント(2週間)
- イベント窓オーケストレーション:
configs/events.yaml
+scripts/scheduler.py
(当日キューで自動ON/OFF) - オートチューン v1(90秒):起動直後の
median_spread_bps
/slip_proxy
からDELTA_FIRE/CLEAR/REFR
を±小幅で補正(write_row("autotune", ...)
) - 真水P/Lの確定度UP:
- 可能なら 手数料実測(fillレスポンス) をログへ
- 線形 funding を
/v5/position/list
等から積算してfunding_accum
に分離
🧪 実験計画(A/Bの型・7日)
テーマ | A(現行) | B(候補) | 成功条件 |
---|---|---|---|
適応fire | 固定 0.012/0.007 | オートチューン値 | take_profit_exit 率↑、hedges 中央値 8–12 |
guard幅 | 4bps | 6bps | realized_net 中央値↑、spread_skip /分↓ |
refractory | 0.8s | 1.0s | hedge_fail 連続<3、realized_net ↑ |
残しΔ | 0 | ±0.003残す | トレンド日でrealized_net ↑、静穏日に悪化なし |
1セッションおきに交互実行、ログは
logs/a_*.csv
,logs/b_*.csv
で区別。
📌 KPI / DoD(Definition of Done)
- KPI(セッション):
exit=take_profit_exit
/realized_net ≥ 0
hedges=8–15
/delta|abs.p95
が帯内 /skips
(spread+cooldown)が制御範囲theta_accum ≤ PNL_TARGET*0.6
(起動5分で≤ 0.3
なら続行)
- DoD:
scheduler.py
から当日2本(22:15/22:45)が自動運転summarize_log.py
で上記KPIが1コマンドで出るtools/replay.py
(最小でOK)で同ログ→同P/L再現- Deadman(
delta_tick
欠落>3s)・Notional cap・Rate-limit上限で停止ログが出る presets.yaml
に勝ち窓プリセット≥3(CPI/雇用統計/米株OPC など)
🔒 運用・セキュリティ注意
- API鍵:
.env
やenv.example
にはダミー、本物はシェルでexport。 - ログ:P/Lやイベントログは公開リポジトリへコミットしない(
.gitignore
済)。 - 時刻:NTP同期。
server-time skew
警告が出たら即調整。
⏱ 今夜の実行(決め打ち)
1本目 22:15–22:30 → 解析→つまみ1段 → 2本目 22:45–23:00(再現確認)
終わったら、末尾5–10行(hedge_ok/hedge_pnl/exit/unwind_*
+theta_accum
+autotune
)を貼ってください。数字で FIRE/CLEAR / SPREAD_GUARD / REFRACTORY / THETA_BUDGET
を最終調整します。
現在、上記項目のオートチューン化に取り組み中。