本日は、止める→見える→触れるまで一気に進めた日でした。しかし、「止めの基盤」と「EV検証」の部分がまだ数字と噛み合ってない部分もあるので、明日はこの点を潰していくのがメインタスクになりそうです。
以下の4つに加えてガンマスキャルピングbotの雛形も作成しましたが、実装レベルに満たないため本日の掲載は省略します。
【明日のbot開発覚書】
・CEX/DEX arb:閾値の大幅いじりと新監視の追加はもうやらない。打席を増やす。
・清算スナイプ:窓/TTLは固定。いじるのやめる。
・全体:EV(期待値)証明が後ろ倒しになりがち。基盤の詰めにリソース(時間&学習)を使いがち。「触った結果が+かどうか」の証拠を集めるべき。— よだか(夜鷹/yodaka) (@yodakablog) August 18, 2025
MMbot作業ログ
0) ゴール
- 自動停止メカニズム(Alert →
/am-webhook
→disable_live
)の完成 - p99/RPS の安定観測とKPIメトリクス基盤の常時可視化
1) タイムライン(重要イベント)
- [構成修正] Exporter と Runner の単一プロセス統合(/metrics & /emit & /control & /am-webhook を同一REGで提供)
- [配線修正]
/control
実装(POST, X-Auth-Token)→ Runner のnew_orders_enabled=False
に連動 - [REG問題解決] REG ID不一致(別プロセス)の解消。ホットパッチで
/app/mm_bot
に直接差し替え - [重複メトリクス]
Duplicated timeseries
の排除(宣言の重複を整理:Runner側に一意、Monitor側と二重にしない) - [録画式反映] p99/RPS 録画ルールを
*_seconds_bucket
前提の式に統一(低トラフィック耐性つき) - [ウォームアップ]
/emit
経由で観測データ注入(WARM)→ Prom 側で p99/RPS を非NaN化 - [KPI基盤]
mm_ev_order_total
を /metrics に掲載(発注時インクリメントの足がかり)
2) 実測・検証結果
- /control:HTTP 200(手動停止OK)
- p99 / RPS:
mm_total_p99_ms:5m
= 832.16 msmm_total_obs_rps:5m
= 0.3221
- ヒストグラム:
mm_lat_total_seconds_bucket
の行数 = 60 - KPI掲載:
mm_ev_order_total 0.0
(メトリクスは可視、配線は最小) - (一時未達)
disable_live reason=...
の理由ログが未表示(/control は効いているがログが拾えない場面あり)
3) 主要な問題と対処
3-1) 古いコードが走っていた
- 兆候:
HAS_control_counter=False
など - 原因:ビルド反映漏れ/
/app/src
ではなく/app/mm_bot
配置だった - 対処:ホットパッチで
/app/mm_bot/...
に直接runner.py
/http_exporter_std.py
をdocker cp
→ 再起動
3-2) Duplicated timeseries
- 兆候:起動時に
Duplicated timeseries in CollectorRegistry
- 原因:同名メトリクスの二重宣言(Runner と Monitor)
- 対処:宣言を一意の場所に集約、他は参照のみに変更
3-3) p99 が NaN / RPS = 0
- 原因:観測不足 or 録画式が
_agg_
参照 - 対処:
*_seconds_bucket
を参照する式に統一+WARM注入 → 解消
3-4) disable_live
の理由ログが出ない
- 可能性:logger設定/ハンドラ登録のタイミング、stdout不達
- 対処案(実装方針):
_disable_live()
を logger+stdout の二重出力に修正(パッチ準備済み)
4) 現在地(達成度)
- 制御フロー基盤:100%(/control 200、停止フラグ、Webhook口あり)
- メトリクス収集:100%(p99/RPS 非NaN、bucket 60)
- KPI基盤:70%(order は見える/fill・reject・P/L分解は配線中)
- ログ出力(停止理由):90%想定(二重出力パッチ適用で確実化)
総合進捗:~80–85%
5) 直近の改善パッチ(最小差分・要点のみ)
5-1) _disable_live()
の確実ログ化
# src/mm_bot/core/runner.py import logging, sys ... def _disable_live(self, reason: str = "no_reason"): self.new_orders_enabled = False mm_control_actions_total.labels(action="disable_live").inc() msg = f"disable_live reason={reason}" logging.getLogger("mm_bot.control").error(msg) # logger経由 print(msg, flush=True) # stdout保険
5-2) Exporterでの受信ログ(任意)
# src/mm_bot/services/http_exporter_std.py (/control 分岐) logging.getLogger("mm_bot.control").info(f"control executed: disable_live reason={reason}")
5-3) KPIの“配線”を最低1行ずつ
- 発注成功:
mm_ev_order_total.inc()
- 約定:
mm_ev_fill_total.inc()
+mm_pnl_components_total.labels(kind="spread").inc(spread_jpy)
- 拒否:
mm_ev_reject_total.inc()
6) 即時チェック(3本)
# A) /control → 200 → カウンタ増分&理由ログ1行 curl -s -X POST http://localhost:8080/control \ -H "X-Auth-Token: mm-bot-control-2024" -H 'Content-Type: application/json' \ -d '{"action":"disable_live","reason":"manual_test"}' -w "\nHTTP:%{http_code}\n" curl -s http://localhost:8080/metrics | grep -m1 '^mm_control_actions_total{action="disable_live"}' docker logs mm-bot-mainnet --tail 200 | grep -i "disable_live reason=" | tail -1 # B) p99 / RPS(非NaN/非0の継続確認) curl -s 'http://localhost:9090/api/v1/query' --data-urlencode 'query=mm_total_p99_ms:5m' curl -s 'http://localhost:9090/api/v1/query' --data-urlencode 'query=mm_total_obs_rps:5m' # C) KPI 1本(order) curl -s http://localhost:8080/metrics | grep -m1 '^mm_ev_order_total'
7) 次フェーズ(完了後 30〜60分)
- Alertmanager E2E:
/am-webhook
で Critical firing →disable_live
1行ログ - Grafana 4パネル(プリセット):
- Fill/Reject 率(5m)
- SpreadPnL(日次合算)
- Cancel p95(ms)
- 実行RPS
- Paper EV/bp ミニ集計(CSV→日次EV、分解4要素)
MMbot達成度(「稼ぐ」をゴールにすると)
約 50%(±7%)
土台はかなり前進しましたが、“お金を生む証明”=EV>0 の実証が未了です。いまは「止められる・見える・流れる」段まで整い、**“勝てるかを示す”**の最終区間が残っています。
内訳(重みづけ評価)
項目 | 重み | 現状達成 | 加点 |
---|---|---|---|
アルファ/EV検証(Backtest→Paper→最小Live) | 40% | 20% | 8 |
実行/レイテンシ(p99/RPS、配線) | 25% | 70% | 17.5 |
リスク/自動停止(Alert→disable_live) | 15% | 70% | 10.5 |
可観測性(/metrics, Prom, 録画式) | 10% | 90% | 9 |
運用/オペ(手順化・スケール準備) | 10% | 50% | 5 |
合計 | 100% | ≈50 |
いま効いている:/control 200、p99/RPS 非NaN、同一REG、KPI基盤(order)
まだ:disable_live
理由ログの確実化(微修正)、fill/reject/PnL のKPI配線、Paper→最小LiveのEV実証
ここから 70% に跳ねさせる“3本”
- Paper 24–48h(現実寄り Fill 模型)
- 受け入れ:EV>0 / Fill≥35% / Reject≤3%
- KPIの配線を3行だけ追加(各イベントで1行)
- 発注成功:
mm_ev_order_total.inc()
- 約定:
mm_ev_fill_total.inc()
+mm_pnl_components_total{kind="spread|fees|…"}
- 拒否:
mm_ev_reject_total.inc()
- 発注成功:
- 停止E2Eの確証
/am-webhook
→disable_live reason=…
がログ+カウンタで残ることを確認
“Go/No-Go”の受け入れ基準(最小Liveへ)
- Prom:
mm_total_p99_ms:5m
非NaN、mm_total_obs_rps:5m
> 0(継続) - Paper 24–48h:EV>0 / Fill≥35% / Reject≤3%
/am-webhook
→ 停止ログ1行+mm_control_actions_total{action="disable_live"}
増分- 最小Live(1×, 1日):ネットPnL ≥ 0
MMbot開発:今日の“筋の悪い”ところ(短評)
- インフラの最終1%に時間を使いすぎ
/metrics・/control・REG統一は既に“勝つための必要条件”は満たしていました。そこからログ体裁やプロセス競合の詰めに長く滞留し、EV証明の着手が遅れたのが痛い。 - KPI配線が“基盤止まり”
mm_ev_order_total
は出せたのに、fill / reject / PnL分解の1行配線を後回しに。
→ P/Lの内訳が見えない = 明日の意思決定ができない(最短経路を外す典型)。 - 反映戦術がブレた(ビルド vs ホットパッチ)
build中断→ホットパッチ→再起動…の流れで、/app/src と /app/mm_bot の差に振り回されました。
→ 「今日はホットパッチだけ」など手段を固定し、確認コマンドをテンプレ化すべき。 - “止めた”事実の監査が弱い
発注スキップは効いているのに、disable_live reason=...
の監査ログが未出力のまま先へ進んだ。
→ “止まる”は利益を守る最後の柵。ログ+カウンタの二重で即可視化が最短。 - 実験の受入基準/終了条件の宣言が薄い
「いつをもってOKで次へ進むか」が曖昧で、作業の終点が伸びる。
→ “p99/RPSが数値→KPI3行→Paper 60分”の順番ロックを掛けるべきでした。
明日の改善プラン(3時間で70%ラインへ)
ブロックA(45分)— 停止の監査を確実化
- Runner
_disable_live()
を logger+stdout 二重出力に(今日のパッチ案でOK)。 - 受入:
/control
200 →disable_live reason=manual_test
がログ1行mm_control_actions_total{action="disable_live"}
が +1
ブロックB(60分)— KPI配線を“3行だけ”
- 置く場所は最低3箇所:
- 発注成功直後 →
mm_ev_order_total.inc()
- 約定ハンドラ →
mm_ev_fill_total.inc()
+mm_pnl_components_total{kind="spread|fees|slippage|adverse"}
- 拒否ハンドラ →
mm_ev_reject_total.inc()
- 発注成功直後 →
- 受入:
/metrics
で各メトリクスが見え、WARM/ドライランで非0になる。
ブロックC(45分)— Paper 60分スモーク→EV/bp
- 先頭距離×確率+部分約定の“簡易モデル”でOK(既に実装済みベース)。
- 受入:
EV/bp(spread/adverse/fees/slippageの分解付き)
を1枚出力。
ブロックD(30分)— Alertmanager E2E
/api/v2/alerts
に firing POST →disable_live
ログ+カウンタで確認。- 受入:
MMBotLatencyCritical
firing→ 停止の事実がログに残る。
明日のガードレール(迷いを潰すルール)
- Exporter/REGには触れない(凍結):/app/mm_bot のホットパッチのみ。
- “ビルド or ホットパッチ”を開始時に固定(明日はホットパッチのみ推奨)。
- 各ブロックに明確な受入条件(上記の「受入」を満たしたら即次へ)。
- 作業前にこの2行だけ実行:
→ 赤が出たら基盤、数値が出たらKPI/EVへ。迷わない。
docker exec mm-bot-mainnet python -c "import mm_bot.core.runner as r; import inspect; print('HAS_disable_live=', 'disable_live reason=' in inspect.getsource(r.Runner))" curl -s 'http://localhost:9090/api/v1/query' --data-urlencode 'query=mm_total_p99_ms:5m'
一言まとめ
- 今日の躓きは 「基盤の1%詰め」>「EVの可視化」 に偏ったこと。
- 明日は “停止ログ1行+KPI3行+EV1枚” を時間箱でやり切るのが最短ルート。
CEX/DEX arbbot開発ログ
1. 立て直し・計測開始
status_now.py
で健全性確認:watcher=UP/killswitch=UP、429カウンタ=0- 時間帯制御ON:
time_slot_control.sh
(USオープン±30分のみ自動GO) - 近接アラート再起動(単発化のため
flock
):near_go_alert.sh SOL 0.05
(AUTO_TH
採用時のみ自動GO)near_go_alert.sh RAY 0.03
2. Jupiter応答の堅牢化(KeyError/data対策)
fetch_now.py
:汎用パーサ_parse_jup_out_usdc
追加data[0].outAmount
/ トップレベルoutAmount
/routes[0].outAmount
/otherAmountThreshold
に対応
- 直ルート+最良ルートの二段取得、安い方を採用
- amount=0.8 SOL、slippageBps=20 に最適化
3. “叩かない”設計(429抑止)
rate_guard.sh
を適応式に:GUARD_SEC
基本+429回数で自動延長fetch_now.py
のget()
で 429検知→カウント/成功→0リセット
4. 刺す直前の制御(AUTO→GO 0%対策:ミニパッチA/B/C)
- A: 1stヒット後クールダウン解除 → 2ndヒットを1–2sで確実評価
- B: last-look の計算式を preok と統一(同MID)→ 境界誤キャンセル抑制
- C: WHYログ分解 を導入(stage=gross0/gross10/depth/dry8/preok_false/last_look)
5. depthでの空振り抑止(当たり寄せ)
ladder_try_now.sh
:VWAP-BIDの採用($10を呑める平均価格)- (拡張)
depth_ok_any.py
作成:OKX/Binance/BybitのVWAPを比較し最良VWAPを採用
6. 観測ログ(第1→第2回)
- 第1回:NEAR=1 / AUTO=69 / GO=0、
skip={'pre-net':53, 'gross<0':84, 'gross<10':2}
- 第2回:NEAR=1 / AUTO=85 / GO=0、
why={'depth':6}
(WHY生成開始)
→ AUTO↑(+16)、depthで落ちていることが可視化
7. 運用・調整ノブ(If/Then)
gross<0
多い → CEX優先/VWAPを維持(OKX→Binance→Bybit)pre-net
多い → 0.8SOL/20bps・fx_bp自動反映を維持- AUTO→GO<30% が継続 → TTLを 2.5s→3.0sへ +0.5s 、429平均>1なら
GUARD_SEC=2
8. 今日のDone基準(据え置き)
- 二重ゲートで新規5本(NO-GOは不足数値ログ)
- 5本サマリ:win_rate>0.60 & avg_pnl>0(未達→実行ライン±1bps)
exec_log.jsonl
:{ts,tap,pre_net,fx_bp,ladder,dq,df,cb,cf}(+need_delta_px
/tap_age_sec
があれば尚良)
CEX/DEX arbbot:総合評価(いまの立ち位置)
- 総合達成度:40% ±5%(目安) 収益化の“土台”はほぼ整備済みだが、**実行フェーズ(AUTO→GO→約定)**でまだ刺さっていない状況。
軸別スコア(根拠つき)
軸 | 達成度 | 根拠(直近ログから) |
---|---|---|
インフラ/監視 | 90% | watcher/killswitch=UP、429適応ガード=0、flock導入済み、時間帯制御ON |
価格取得/レート制御 | 85% | fetch_now堅牢化(Jupiter汎用パーサ、直/最良ルート、0.8SOL/20bps、キャッシュ+バックオフ) |
実行パイプライン(NEAR→AUTO→GO) | 55% | NEAR→AUTOは十分(直近200行でAUTO=69→85へ改善)だがGO=0。2ヒット/last-look/深さで止まる |
フィルタ・安全性(ムダ打ち抑止) | 80% | gross<0/gross<+10/dry pre-net<+8/depth/VWAP/last-look の多層フィルタ完備 |
アルファ/シグナル品質 | 25% | gross<0が最多(84件)、pre-net不足(53件)。TRADES=11・win_rate=0 |
データ量/再同定可能性 | 30% | 実弾N=11は統計が薄い。near-goスナップショットは蓄積中(p50 needΔ≈0.0112 USDTと“近い”が未到達) |
目下の主要ブロッカー(AUTO→GO=0の原因)
- 板厚不足(WHY: depth):$10を一撃で呑めるBIDが不足(stage=depth 記録あり)
- 境界判定の取りこぼし:2ヒットのTTL/COOLDOWN/last-lookの直前ロジックでキャンセル
- CEX_BID ≤ DEX_Qの場面が多い(gross<0=84) → そもそも到達しにくい時間帯/銘柄が多い
今週の“進捗が見える”目標(Done定義の落とし込み)
- 量:二重ゲートで 新規5本(NO-GOは不足数値ログ)
- 質:5本サマリ win_rate > 0.60 & avg_pnl > 0
- ログ:
exec_log.jsonl
が {ts,tap,pre_net,fx_bp,ladder,dq,df,cb,cf}(+必要ならneed_delta_px
/tap_age_sec
)
ここから“稼ぎへ”最短の3手(設計据え置き・即実行)
- 深さで落ちない:最良VWAP×複数CEX を last-look まで貫通
- 既に導入済:
depth_ok_any.py
→ OKX/BNB/BYBIT で $10 VWAP 最良を採用 - 効果指標:WHY: depth 比率が下がること、AUTO→GO比が上がること
- 既に導入済:
- 2ヒットの取りこぼしをさらに減らす
- 1stヒット後COOLDOWN解除は実装済 → **TTLを+0.5s(2.5→3.0s)**に小緩和(429はrate_guardで吸収)
- 効果指標:AUTO→GO ≥ 30% 到達
- 当たり時間帯に集中(USオープン±30のみ自動GO)
- すでにスロット制御ON。**AUTO_TH(SOL 0.015/RAY 0.025)**は据え置き(NEAR→AUTOは十分)
- 429が増えたら一時的に
GUARD_SEC=2
(0.5 req/s)→落ち着いたら戻す
期待値の見立て(短評)
- 土台の完成度は高い(≈85–90%)。
- 勝ちに直結する差分は“刺す直前の数秒”:深さ/VWAP/TTLを詰めればAUTO→GOが立ち上がる見込み。
- 近接度のp50≈0.0112 USDTは“届く距離”。CEX側VWAPが乗った瞬間に、2ヒット+last-lookを通過できるはず。
結論
- いまの達成度:40%前後。
- 短期の勝ち筋:最良VWAP×複数CEX+2ヒットTTLの小緩和+時間帯集中で、AUTO→GOを“0→30%”へ引き上げ、最初の5本で**+PnL**を取りに行く。
- 60–90分計測後の数字(サマリ・ファネル・WHY内訳)を頂ければ、実行ライン(±1bps)/AUTO_TH/GUARD_SECをその場で微調整します。
CEX/DEX arbbot:今日の筋悪ポイント(原因 → 影響)
- AUTOは増えたのに GO=0 を“その場”で潰し切れていない
- 原因:2ヒットTTL/COOLDOWN/last-lookの最終段で落下。変更は入れたが効果確認ループが当日中に回り切ってない。
- 影響:NEAR→AUTOの増加(69→85)に対して、当日の実GOが0のまま。
stage=depth
の未解決を後回し(WHY: depth が早期に可視化された)
- 原因:$10を呑めるVWAP(しかも複数CEXでの最良)を最終段まで一貫適用する処置が遅れた/確認不足。
- 影響:板薄い見かけBidでpreokまで進んで落ちる → AUTO→GOが立ち上がらない。
- ログの“一致”を崩したまま計測を進めた(NEAR=1に対してAUTO=69/85)
- 原因:near_go の多重起動・ログ源の非対称(SOL/RAY混在/旧プロセス生存)を潰す前にファネルを読んだ。
- 影響:NEAR→AUTO の比率評価が歪む→しきい値の調整判断が遅れる/誤る。
- NET_EDGE_MIN_BPS が unset の時間帯があった
- 原因:環境変数の輸出忘れ/表示上の食い違い。
- 影響:Watcherの表示・挙動の不一致リスク(実行ラインの誤認)。
- “時間帯と負荷”より“設定の微修正”を優先
- 原因:429/awkなどのインフラ改善に時間が割かれ、USオープン±30の当たり時間帯での刺し込みが薄くなった。
- 影響:当たり母集団を取りに行く機会損失。ログは増えたが、稼ぐための打席が増えていない。
明日の改善アクション(90分プラン)— “刺さる”に一点集中
A. 最終段を一気に通す(AUTO→GO ≥30% にする)
- TTL 小緩和を当日中に検証(+0.5s)
- いま 2.5s → 3.0s へ。
- 成功条件:AUTO→GO ≥30%(直近200行で GO≧60×0.3)
- VWAP×複数CEX を last-look まで一貫適用(落ち所=depth潰し)
depth_ok_any.py
の 最良VWAP を preok直前→last-look直前の両方で採用(CBの上書き一貫)。- 成功条件:
why_breakdown
の depth 比率↓、GO増加。
- 単価サニティ(unit mismatch)で“異常値”は即キャンセル
abs(cb−dq)/mid < 0.10
を満たさなければ[WHY] unit_mismatch
で落とす。- 成功条件:誤発射ゼロ(NO-GO理由に unit_mismatch が出たら観測)
B. 観測→判断→即ノブ(10分×2回)
- ログの一致を先に担保
pkill -f near_go_alert.sh
→source time_slot_control.sh
→ 単発起動(flock済みでも古い個体は止める)。- 成功条件:NEAR の増加に対して AUTO が過大にならない(NEAR≲AUTO)
- ファネル+WHYで即判断
summary_5_trades.py
(skip + WHY 内訳)/NEAR・AUTO・GO の3値。- If/Then
- AUTO→GO <30% かつ WHY=depth 多い → GUARD_SEC=2(429抑止&連打抑制)
- WHY=last_look 多い → TTLを +0.5s(最大3.0sまで/戻しは数字で)
- NEAR→AUTO <10% → AUTO_TH を SOL 0.015→0.02、RAY 0.025→0.03 に +0.005 のみ
- 当たり時間帯に集中
- 迷わず USオープン±30分だけ自動GO、他時間は通知のみ。
- 成功条件:その時間帯に GO が立つ(ladder_watch.log に “GO (ladder …)” が出る)
C. ガード(落ちない工夫)
export NET_EDGE_MIN_BPS=38
を明示輸出 →check_main_watcher.sh
再起動- 429 が 10分平均で >1 → 一時的に
export GUARD_SEC=2
(戻すときはunset GUARD_SEC
)
“やらないこと”(明日は削る)
- しきい値の大幅いじり(±1bps以上の変更)
- BTC再挑戦(Jupiter mint/ルートが健全化するまでOFF)
- 新しい監視や可視化の追加(WHY内訳・ファネルが揃っている)
できていた良い点(このまま維持)
- Jupiter堅牢化(汎用パーサ、直/最良ルート、0.8SOL/20bps)
- 適応レートガード(429=0)
- 多層フィルタ(gross/乾式pre-net/depth/VWAP/last-look/2ヒット)
- 時間帯制御(USオープン±30の集中)
一言でまとめると
- 筋の悪さは、「最終段の数秒」を今日中に詰め切れず、当たり時間帯の打席を増やし切れなかった点。
- 明日は:最良VWAP×複数CEX一貫適用+TTL+0.5s+時間帯集中で、AUTO→GOを 0%→30% まで引き上げ、最初の5本に到達する。
オンチェーン精算スナイプbot:作業ログ
概要
- 目的:REPLAY基準で KEEP≥60% / p95≤350ms を達成し、その後 drop≤10% を“測れる状態”へ。
- 現在地:p95=300ms 達成、KEEP=48%(16%→48%へ大幅改善)。ltK(insufficient_kinds)支配が残課題。
1. 基盤・計測の是正(統一・可視化)
- 設定一元化:
runtime.R
にALIGN_MS / KEEP_CONFIRM_MS / JOIN_WINDOW_MS / TTL_MS / KEEP_CONFIRM_STEPS_MS=[KEEP, KEEP*2]
を集約。 - 時刻正規化(sec/µs/ns→ms)& ALIGN依存へ統一。
align_ms_current
を/metrics
で公開。 - REPLAYの flush を十分未来へ変更:
future = last_ts + KEEP×2 + ALIGN + 200ms
。 - Registry統一:すべて
get_registry()/self.m
経由に修正し、default混入を排除。
効果
- p95 が 1000ms固着→300ms へ正常化(ALIGN=300ms)。
2. KEEP確認回路の可視化・安定化
- 確認ジョブ系メトリクス追加:
confirm_(scheduled|processed|kept|faded)_total / heap_depth / next_at_ms
。 - exactly-one 設計:JOIN未成立/KEEP失敗の各出口で miss 理由を必ず1つ
inc()
。 keep_wait_ms
(JOIN→KEEP遅延)/fade_alive_kinds
(最終確認での生存種)を追加。
実測
confirm_scheduled=confirm_processed
、kept+faded ≈ processed
を確認(正常動作)。
3. 片翼死の直叩き(fade対策)
- 弱条件 refresh 実装(毎tick/最小間隔80–100ms):FIREは据置、REFRだけ1クリック緩和。
- 心拍パルス 実装:JOIN→KEEPの間、80–100msごとに missing側だけ refresh(JOIN水増しなし)。
実測
confirm_pulse_total
大量、confirm_faded_total → 0
、fade_alive_kinds
偏重解消。- KEEP 16% → 48% に改善。
4. ltK(K=2未達)への対処(K到達率↑)
- FIREしきい 1クリック緩和(段階的):
- 例)
OI_Z: 1.5→1.4 / BBO_COLLAPSE: 3.5→3.0 / L2_THIN: 0.72(据置)/ BURST_BP: 7(据置)
- 例)
- 以後の攻め案(必要時):
L2_THIN: 0.72→0.75 / BURST_BP: 7→6
実測
- JOIN増・ltK比率の低下を確認(KEEP=48%まで上昇)。
- ただし
insufficient_kinds≈886
がなお支配的 → さらなる1クリックが必要。
5. 窓/TTL(現行セット)
ALIGN_MS=300 KEEP_CONFIRM_MS=450 JOIN_WINDOW_MS=700 TTL_MS=3000 REQUIRE_PAIR=0 REPLAY_MODE=0
- ルール:TTL ≥ KEEP_CONFIRM×2 + 100ms を厳守。
keep_wait_ms
ピーク(400–600ms/900–1200ms帯)と矛盾なし → 現状据置で良好。
KPIスナップショット(最新)
- p95:300ms(ヒスト算出/ALIGN=300)✅
- KEEP:48.0%(16%→48%)↗️
- fade:0件(
confirm_faded_total=0
)✅ - ltK:
insufficient_kinds≈886
❗(残課題)
次の一手(1クリック)
- 目標:KEEP 48% → 60%+(p95は維持)。
- 実施:FIREを1クリック(K到達率↑、質は維持)
OI_Z: 1.4→1.3
/BBO_COLLAPSE: 3.0→2.8〜3.0
- (必要なら)
L2_THIN: 0.72→0.75
/BURST_BP: 7→6
- 観測:2行ヘルス+
insufficient_kinds / keep_wait_ms / fade_alive_kinds / confirm_*
を5分ループで確認。 - ガードレール:p95>350ms or keep%<50% になったら直近変更をロールバック。
その次:drop計測ON(影/実 4カウンタ)
shadow/live_exec_attempt_total
、shadow/live_fill_success_total
を配線 →fill_rate_shadow/live
とdrop = 1 - (live/shadow)
(目標 ≤ 10%)を常時計測。
オンチェーン精算スナイプ:達成度
ざっくり結論:達成度は ~56%(私の目安) です。
「動く・測れる」は整い、p95=300msもクリア。一方でKEEP=48%(目標≥60%)と、drop≤10%の計測/EVゲートが未達。
いまの達成度(重み付きざっくり採点)
- 検知/シグナル実装(20)… 14/20(主要シグナル+整流OK)
- 合議品質(20)… 11/20(KEEP 16%→48%へ大幅改善、目標60–90%まで一歩)
- レイテンシ(15)… 12/15(p95=300ms:ALIGN依存で安定)
- 執行品質/ドロップ(15)… 2/15(shadow/live dropの4カウンタ未配線)
- 会計/EVゲート(10)… 3/10(日次EV→昇格ラインは未運用)
- 監視/可視化(10)… 8/10(confirm系・keep_wait・fade分布まで可視化)
- 安全/運用(10)… 6/10(冪等化・ガード類OK、ゲート最終確定はこれから)
合計:56/100
できていること ✅
- p95=300ms 達成(ALIGN=300ms依存で正常)
- KEEP=16%→48% まで改善(fade=0に収束)
- 確認ジョブ(予約→処理→保持/失敗)メトリクスで動作が数で証明
- 設定・時刻正規化・Registry統一、測定の基盤は安定
まだのこと ❌
- KEEP ≥ 60%(ltK=886が支配 → K=2到達率の底上げが必要)
- drop ≤ 10% の“計測”そのもの(shadow/live 4カウンタ)
- 手数料込みEV>0の運用ゲート(5営業日連続、MaxDD制御)
すぐ上げるための“次の1クリック”
- FIRE だけを段階的に緩めて ltK削減(p95はALIGNで維持)
- 例:A:OI_Z 1.4→1.3, BBO 3.5→3.0(L2/BURST据置)
- 効果が小さければ B:L2 0.72→0.75, BURST 7→6
- drop 計測 ON(影/実 4カウンタ)
shadow/live_exec_attempt_total
,shadow/live_fill_success_total
→drop = 1 - live/shadow
を常時計測
KPI判定(REPLAY基準):KEEP≥60% / p95≤350ms / insufficient_kinds↓ を満たせば、低ノッチCanaryで drop≤10% を見に行けます。
Go/No-Go の“稼ぐ”基準(再掲)
- KEEP ≥ 70–90%
- p95 ≤ 350–400ms
- drop ≤ 10%(shadow vs live)
- 手数料込みEV>0 を 5営業日連続(MaxDDは許容内)
清算スナイプbot:今日の“筋が悪かった”ポイント(なぜ悪い→どう直す)
- 複数ノブを同時に動かした
なぜ悪い:因果がぼけて、効果検証が遅れる(KEEP%が上がった/下がった理由が不明)。
どう直す:1クリック=1ノブ。A/B(前後)でjoin/keep/keep%/p95/insufficient_kinds
を必ず比較。 - パルス/refreshの“対象”が広すぎた(当初)
なぜ悪い:missingでない側も延命→JOIN質が落ちやすい・CPU浪費。
どう直す:missing側限定(JOIN時 alive ∪ 現在 alive ∪ near)− 今alive だけに refresh。 - 窓/TTLをいじり続けた(既に fade はゼロ)
なぜ悪い:ボトルネックは ltK(K未到達)。窓/TTLはもう効かない。
どう直す:窓/TTLは ALIGN=300 / KEEP=450 / JOIN=700 / TTL=3000 で固定。以後は FIRE/REFR/pulse だけ。 - 再生プロセスの不安定運用(ポート衝突・旧メトリクス参照)
なぜ悪い:古い結果を見て判断誤り。
どう直す:1プロセス運用+ 起動順の固定(start_http_server(..., get_registry())
→ScoringEngine()
)+ 強制 flush。 - KPIの“反応速度指標”を見ていなかった
なぜ悪い:パルスやREPRの効き所が分からない。
どう直す:keep_wait_ms と fade_alive_kinds を必ず見る(ピーク帯&最頻値)。今後の窓合わせの根拠に。 - ltKをFIREで削る判断が遅れた
なぜ悪い:fadeが消えた時点で、次のボトルネックは明確に ltK。
どう直す:FIREだけ段階的に緩める(REFR/窓は据置、p95はALIGNで固定)。 - “稼ぐ”直結の drop 計測が後ろ倒し
なぜ悪い:KEEPが上がった瞬間に drop を見始めるべき。
どう直す:keep≥60% 到達直後に影/実の4カウンタ配線(attempt/fill_success)。
明日の“最短”プラン(午前で勝ち筋確認)
0. ルール(固定)
- 窓/TTL:
ALIGN=300 / KEEP_CONFIRM=450 / JOIN_WINDOW=700 / TTL=3000
固定 - パルス:80ms、missing側限定 refresh(実装済)
- REFR:毎tick、最小間隔 80ms、近い閾値(実装済)
1. 検証ループ(1クリックずつ)
段階A(保守的) — まずこれ
- FIRE:
OI_Z 1.4→1.3
、BBO 3.5→3.0
(L2/BURST据置) - 再生 → 2行ヘルス+内訳
- 合格:
keep≥60% / p95≤350ms / insufficient_kinds↓
→ drop配線ONへ - 未達:段階Bへ
- 合格:
段階B(攻め) — Aで伸びが小さければ
- FIRE:
L2_THIN 0.72→0.75
またはBURST 7→6
(一度に片方だけ) - 再生 → 同じKPI判定
- p95>350ms or keep<50% に落ちたら直前をロールバック
いずれも 1クリック=1ノブ を厳守。A/B前後をCSV出力すると迷いません。
2. 合格したらすぐ drop 計測ON(影/実4カウンタ)
shadow/live_exec_attempt_total
、shadow/live_fill_success_total
- レポート:
fill_rate_shadow/live
、drop = 1 - (live/shadow)
(目標 ≤10%)- 2行KPIに
drop
を追記(明日中に“測れる状態”へ)
明日の作業チェックリスト
- 起動順:
http_server→ScoringEngine
(Registry統一) - セット固定:
ALIGN=300/KEEP=450/JOIN=700/TTL=3000
- 段階A FIRE 1クリック → 再計測
- 合格 or 段階B FIRE 1クリック → 再計測
- すぐ
drop
4カウンタ配線 - 2行ログ+
insufficient_kinds
+keep_wait_ms
ピーク+fade_alive_kinds
最頻値を保存
成果目標(明日中)
- KEEP ≥ 60%(p95は維持)
- drop 計測ON(影/実)
- 以降:EVゲートへ
短く言えば、**“FIREだけ一段ずつ”**が明日のコア作業です。
ショート系bot:作業ログ
0) サマリー
- ゴール:24h Testnet Canary → α判断
- 進捗:/metrics 集約完全復旧、CB表示の二重化(真実値agg)、数量ゼロ丸め根絶、Canary Smokeのtaker ping実装、発注系4カウンタ導入。
- 残タスク:実 fill の安定発生(EVメトリクス通電)※IOC待機/価格/size or Market pingで即解決可
1) 計測・集約まわり(復旧〜強化)
実装
metrics-serve
を symlink/tmp/bsb_mp/current
集約に変更(env→import順序を厳守、WSGIでregistry=
明示)。- epoch切替:起動時に
run-<ts>
を生成 →current
に相対symlinkを張替え。 - ジャニター:stale PID を
mark_process_dead
で定期掃除(手動metrics-janitor --ttl-sec
も可)。 - metrics-sanity で aggregated registry の中身を直検査できるように。
- CB真実値:JSON直読の
short_circuit_state_agg{category}
を serve 側 Collector で追加(mp残骸に非依存)。
検証・結果
mini_counter_total
が /metrics に出現 → 集約復旧 OK。short_req_ack_ms_* / short_cancel_ms_*
の bucket/sum/count 出現を確認(dryrun 10本)。- CBドリル:
error-sim → health-sim-recover
で 2→1→0 を/metrics
と JSON の両方で整合。- ダッシュは
short_circuit_state_agg
を既定に。
- ダッシュは
2) 収益メトリクスと可観測性(増強)
実装
- 収益メトリクス(EVの分解と集計)を配線:
short_ev_bps_total|_count
,short_trades_total
,short_win_trades_total
,- スリッページ分離:
short_slip_cost_bps_total
(max(slip,0)),short_price_improve_bps_total
(max(-slip,0))
- 発注系4カウンタ(ゼロ詰まりの切り分け用):
short_orders_sent_total
,short_cancels_total
,short_reject_total
,short_fills_total
- 数量ゼロ丸め対策:
qty_from_notional(price, min_notional, min_qty, step)
を新設(ceil系+min強制)。 - Canary Smoke拡張:
--interval-sec
,--duration
,--taker-every N
,--min-notional-usdt
- taker ping(IOC or Market)で確実に fill を狙える経路を追加
検証・結果
- 4カウンタの テスト記録:
orders_sent_total/cancels_total/fills_total
が /metrics に出現(動作OK)。 - 数量:
min_notional=50
指定で BTCUSDT qty≈0.001
に量子化、0丸めなしを確認。 - EVメトリクス:fill 未発生時は
ev_bps_count=0
(想定どおり)。
3) Canary / Gate / ENV
実装
load_settings()
経由で ENV オーバーライドを適用(CANARY_ENABLED=true
,CANARY_RATIO
,MAX_NOTIONAL
など)。- Canary gate の“サンプリング5%”に詰まるケースに備え、デバッグ時は
CANARY_RATIO=1.0
で通す手順を整理。
検証・結果
preflight
OK、canary-smoke
実行・ループ稼働(post_only→即cancel と taker ping が選択可)。
4) いまの指標スナップ(代表的なものだけ)
- 発注系:
orders_sent_total↑
,cancels_total↑
,reject_total=0
,fills_total=0
(=まだ実 fill 未発生) - レイテンシ:
short_req_ack_ms_* / short_cancel_ms_*
が蓄積(dryrun/Smokeで確認済) - CB:
short_circuit_state_agg == 0
(平常時)
5) いま残っている詰まり(1点)
- 実 fill が未発生 → EV系が動かない
- 有力因:IOCの置き方/待ち方/サイズ あるいは 約定レポート待機(WS/REST)未配線
- 切り分けに
short_ioc_timeout_total{mode,symbol}
(未実装なら追加)を推奨- 発注は通るのに fill/done が返らない場合に増える
6) 次の一手(10〜20分でEVを動かす)
python -m src.cli canary-smoke --symbol BTCUSDT \ --duration 120 --interval-sec 10 \ --taker-every 1 --min-notional-usdt 50 --force-market
- 上記ワンライナーででMarket ping で先に1件 fill を作る
→/metrics
:short_fills_total>0
,short_ev_bps_count>0
を先に確認 - IOC に戻して継続
- 価格:SELLは best_bid - 1tick(
floor_to_tick
) - キャンセル/置換禁止(IOCは1発完結)
- 2.0s待機で
await_fill_or_done()
(WS or 200ms×10 REST)
- 価格:SELLは best_bid - 1tick(
- 10分Smoke(コスト最適化)
--taker-every 6
(1分に1回 taker)へ戻す- Go判定:
EV_bps_avg > +3
&win% > 55%
&reject < 1%
&CB==0
以降、比率は 0.02 に戻して 24h Testnet Canary へ。
7) 追加で入れておくと楽な計測
short_ioc_timeout_total{mode,symbol}
(Counter):IOC待機のタイムアウト可視化- 発注ログ(taker経路のみ):
price / qty / orderId / tif / elapsed_ms
を1行
8) DoD(このフェーズ)
/metrics
非空(bucket/sum/count 蓄積)short_fills_total>0
、short_ev_bps_count>0
(EVが動き出す)- 10分スモークで Go判定クリア
- 24h Testnet Canary へ移行
ショート系bot:達成度
約 50%(±10%)
内訳(目安)
- 計測・信頼性基盤:90%
multiprocess集約の復旧、CB永続化+_agg
、ジャニター、収益メトリクス配線、4カウンタ追加、数量ゼロ丸め根絶まで完了。 - 執行性能(短時間):65%
req→ack/cancel のヒストグラム取得は安定。24h連続SLOは未評価。 - 実約定&EV計測:20%
送信/取消/拒否は記録OKだが、実fillが未発生=EV_bps系が未通電。 - 24h Testnet Canary:10%
直前まで準備完了。スモークでEV>0確認→24hが未実施。 - 収益実績:0%
実PnL/EVの連続実績はまだ無し。
いま足りないもの(上げ止まり要因)
- 実fillの安定発生(IOCの価格・待機・サイズ or Market ping)
- EVページの通電(
ev_bps_total/count
が実トレードで伸び始めること) - 24h連続SLOの実測(
req→ack p99<250ms / cancel p99<300ms / reject<1% / CB=0
)
60%へ上げる最短手順(今日〜明日)
- Market ping(確実に1件fill) →
short_fills_total>0
&ev_bps_count>0
をまず作る - IOC経路で継続:SELLは
best_bid-1tick
、キャンセル/置換禁止、2.0s待機 - 10分スモーク(taker-every=1→6):
Go:EV_bps_avg>+3
&win%>55
&reject<1%
&CB=0
- 24h Testnet Canary:比率0.02で連続SLOとEVを検証
ここまで通せば 達成度は60〜65%、EV>0の連続実績が乗り始めた段階で70%台に入ります。
ショート系bot:本日の筋悪ポイント
きょうの動きを“稼ぐ最短経路”基準で振り返ると、筋が悪かった(回り道になった)点は主に5つです。明日の改善アクションもペアで置きます。
1) 「fillが出るか」を最初に確定しなかった
- 筋が悪い理由: EV系は約定が起きない限り永遠に0。にもかかわらず、IOCの置き方/待機/サイズの検証より前に周辺を整え続けた。
- 明日の改善: 最初の1件をMarketで必ず約定させてEV配線を確定→その後にIOCへ戻す。
- 実行例:
python -m src.cli canary-smoke --symbol BTCUSDT \ --duration 120 --interval-sec 10 --taker-every 1 \ --min-notional-usdt 50 --force-market
- DoD:
/metrics
でshort_fills_total>0
、short_ev_bps_count>0
が増える。
2) IOCで“置く/待つ/サイズ”の3点セットが未完了
- 筋が悪い理由: SELL IOC は best_bid−1tick で置く・置換/キャンセル禁止・2.0s待機 が三種の神器。どれか欠けると fill しない/検知できない。
- 明日の改善: 下3点を一気に固定。
- 価格:
ioc_price = floor_to_tick(best_bid - tick, tick)
- 置換/キャンセル: IOC経路では一切呼ばない
- 待機:
await_fill_or_done(timeout=2.0s)
(WSなければREST 200ms×10)
- DoD: Marketを外しても
short_fills_total
が増える/ioc_timeout_total==0
付近に収束。
- 価格:
3) サイズ検証を早めに固定しなかった
- 筋が悪い理由:
min_notional/step/min_qty
を満たさず qty=0 へ丸め→「送ってるのに刺さらない」と誤解。 - 明日の改善: qty_from_notional() を IOC/Market 両方で使用し、最初は
--min-notional-usdt 50
に固定(BTCUSDT, step=0.001想定で qty≒0.001)。- DoD: ログに
spec: tick, step, min_qty
とCalculated qty: ...
を1行出し、qtyが0/未満にならない。
- DoD: ログに
4) “返事が来ていない”を測る指標がなかった
- 筋が悪い理由:
orders_sent↑ & fills==0
でも、rejectなのか、report未到達なのかが判別不能で時間が溶ける。 - 明日の改善:
short_ioc_timeout_total{mode,symbol}
(Counter)を追加し、待機満了時に必ずinc。- DoD:
- rejectなら
short_reject_total
↑ - 未到達なら
short_ioc_timeout_total
↑
→ 根因が1分で判別できる。
- rejectなら
- DoD:
5) 安全運用の切り替えを明示せずに回した
- 筋が悪い理由: デバッグで
CANARY_RATIO=1.0
を使ったまま遷移しがち。事故時に露出が大きい。 - 明日の改善: デバッグ→運用を明示切替。
- デバッグ(最初のfill確認):
CANARY_RATIO=1.0
,--force-market
- 検証(IOCチューニング):
CANARY_RATIO=1.0
,--taker-every 1
- 運用開始(コスト最適):
CANARY_RATIO=0.02
,--taker-every 6
- DoD: 切り替え直後の
/metrics
4行(orders/fills/reject/EV)を残す。
- デバッグ(最初のfill確認):
明日の実行チェックリスト(30–60分でOK)
- Market ping(fill発生の確定)
- 期待:
short_fills_total>0
,short_ev_bps_count>0
- 期待:
- IOC固定(best_bid−1tick/置換キャンセル無し/2.0s待機)
- 期待: Market外しても
fills_total
が増え続ける
- 期待: Market外しても
- サイズ
--min-notional-usdt 50
(qty_from_notional()
)- 期待: qtyログが常に
>= min_qty
- 期待: qtyログが常に
- 時系列4行を保存
curl -s :9523/metrics | grep -E 'short_(orders_sent|fills|reject|cancels|ioc_timeout)_total' curl -s :9523/metrics | grep -E 'short_(req_ack|cancel)_ms_(bucket|sum|count)' | head curl -s :9523/metrics | grep -E 'short_(ev_bps_total|ev_bps_count|trades_total|win_trades_total)' curl -s :9523/metrics | grep -E 'short_circuit_state_agg{category="network"}'
“やめること”メモ(最短経路を守るために)
- REPLAY/インフラの磨き直し先行(fill未確定のまま)
- IOCでキャンセル/置換を混ぜる(fill直前キャンセルの温床)
- 小さすぎる notion(qtyが0に丸められる)
- 板staleness無視(1s超は再取得)
この4点(Marketで1件→IOCで継続→サイズ固定→タイムアウト可視化)を先に通せば、EVメトリクスが動き始め、明日中に「+3bp超/10分スモーク」まで持っていけます。