Bot mmnot 開発ログ

🛠️開発記録#217 (2025/5/11) MMBot 開発ログ 21「デバッグ高速化とリアルタイム計測の導入」

2025年5月11日

前回の記事に引き続き、今回も仮想通貨botの開発状況をまとめていきます。

本稿は、暗号資産マーケット‐メイカー Bot(以下 MMBot)を Docker 環境で運用する際に遭遇した 「ログが出ない/接続箇所が特定できない」 問題を、最短で切り分けるまでの開発メモを整理したものです。
売買ロジックや実運用パラメータは伏せ、公開してもエッジを損なわない範囲の“開発ノウハウ”だけを共有します。

環境依存の落とし穴と対策

症状原因一発解決テクニック
DEBUG が標準出力に出ず、Docker logs が空loguru のデフォルトレベル=INFOlogger.add(lambda m: print(m, end="", flush=True), level="DEBUG")
✓ レベル昇格 ✓ バッファ即 flush
grep では見えるはずの文字列がヒットしないJSON シリアライズで改行が崩れるまず 生ログ を見る → 必要なら jq -r '.message' で整形
WS ストリームが沈黙Subscribe 失敗 or 心拍欠如before/after ws_connect マーカー → 詰まり位置を 0.5 秒で特定

段階的な接続ヘルスチェック

① REST      : ping instruments-info         → OK?
② get_minQty: DBG before / after            → 数値取得?
③ WS connect: DBG before / after            → ハンドシェイク通過?
④ orderbook : HDLR ERR 例外ログ             → パース成功?

REST → WS → パーサ の順に「パイプの詰まり」を潰すと、再現性のあるデバッグ手順になります。


計測用 METRIC 行の設計

10 秒間隔で 運用に直結しない抽象値 だけを残すことで、安全に統計が取れます。

METRIC spr_pct=<%>  spr_ticks=<tick差>  notional=<USD>  loop_ms=<ms>
  • パラメータ (<%>, <USD>) は範囲化 or 正規化して保存
  • loop_ms でボトルネック(DB I/O や API レイテンシ)を即検知

開発ログから得た学び — 2 時間のタイムライン

時刻アクション学び
T+0 minDocker イメージ再構築 → mainnet へデプロイまずは現象再現
+10 minREST 疎通テスト(aiohttp 5 s timeout)外形監視を最小実装しておくと安心
+15 minDBG マーカーを 2 か所挿入レイヤごとに “光を当てる”
+25 minHDLR 例外捕捉 → メッセージ構造を確認仕様変更耐性アップ
+30 minstdout シンクを DEBUG + flushログが「出ない」原因は大抵これ
+35 minMETRIC 行でループ遅延を可視化調整に必要なデータ構造が完成

今後の改善 TODO

項目狙い
24 h ログ収集 → ヒートマップspread × fill の実測から 適切なしきい値 を導出
max_cycles = 0長期計測モードへの切替え
Watchdog + Slack 死活通知稼働中断を 1 分以内に検知
CI に log-lintlevel="DEBUG"flush=True の抜けを自動チェック

おわりに

今回のアップデートで 実行パイプラインの見える化計測フレーム が整備されました。これにより、次フェーズの パラメータ最適化「勘」ではなくデータドリブン で進められます。
同じ問題に悩む開発者の参考になれば幸いです。

👇ラジオで話したこと

きょうは 「MMBotを“静かに”24 時間まわすためのデバッグ&リアルタイム計測テク」 がテーマです。ポイントは ①.envtpljson の安全な設定パイプライン、②Makefile 1行で Mainnet/Testnet を切り替える運用フロー、③Loguru で WARN だけ を抽出して tail 監視するログ設計、④スプレッドが狭い市場では「Fill 0 = 成功」と腹をくくるリスク管理、の 4 本柱です。


1. なぜ「静かな 24 h 監視」が必要?

  • Mainnet 最小ロット(0.0001 BTC)でまず 1 bps だけ差し込むと、板が詰まっている日は 注文が一度も約定しない ことがあります。
  • しかしこの “Fill 0” は 損しない という意味で成功シナリオ。— 市場が開くまで待てる「我慢強さ」を Bot 側で担保しておくわけです。 SQL Easy

2. .envtpljson の安全パイプライン

  1. .env.prod に API キーやロットサイズを保存。
  2. config_mainnet.tpl${BYBIT_KEY_MAIN} のようなプレースホルダを書く。
  3. Makefile
envsubst < config_mainnet.tpl > config_mainnet.json

 — envsubst はシェル組込みではなく GNU gettext に付属するコマンドで、環境変数を一括展開します。 Stack Overflow
4. 生成後はすぐ .gitignore に入っているか確認し、rm -f で掃除。


3. Makefile ワンライナー運用

ENV ?= .env.test   # “?=” は「未定義なら代入」の意
run: $(CONFIG)
	set -a && source $(ENV) && set +a && \
	docker compose run --rm --entrypoint "" $(SERVICE) \
		python -m MMbotbybit.MMbotbybit \
		--lot $(LOT) --max_loss_usd $(LOSS)
  • set -a (セット・ハイフン・エー) は 「読み込んだ変数をすべて export」 の意味。 Stack Overflow
  • ENV=.env.prod make run と打てば 後勝ち ルールで .env.prod が優先されます。

4. Loguru で WARN だけを追う

logger.add("logs/warn.log",
           level="WARNING",
           rotation="10 MB",
           enqueue=True)
logger.add(lambda m: print(m, end="", flush=True), level="DEBUG")
  • flush=True を付けないと DEBUG が バッファに溜まって Docker logs に流れませんLoguruReal Python
  • 端末では tail -F logs/warn.log-F は “ファイル名の切替えも追従” の略なので、ローテーション後も自動で追い続けます。 prefetch.net

5. リアルタイム計測用 METRIC 行

METRIC spr_pct=0.12 spr_ticks=3 notional=24 loop_ms=87
  • 10 秒おきに “抽象値” だけを残し、個別約定情報は書かないので流出リスクが低い。
  • loop_ms が 500 ms を超えたら DB I/O やネット遅延を疑う。ログ設計の基本は「まず可視化,後で最適化」 です。 Better Stack

6. 24 h ランで詰まったポイント & 直し方

つまずき原因即 fix
${…} が残る.env.prod 未定義 → envsubst 空展開変数を追加して再生成
JSONDecodeError数値を "50" とクオートしていた数値は裸の 50 にする Stack Overflow
TypeError: '>' not supportedenv が文字列で渡るfloat(cfg["max_notional"]) でキャスト
Fill が来ないスプレッドが 0.1 bps と狭いcurl で板を取得し S_ENTRY を再調整 Bybit Exchange

7. 今日の学び

  1. “何もしない” もテスト — スプレッドが狭い日はマッチしないのが正解。
  2. ログレベル分離 は tail × flush で 90 % 片付く。
  3. 環境変数を数字にする と JSON 生成エラーが減る。
  4. 小さいコミットを刻むgit revert で 10 分ロールバックが可能。 Stack Overflow

一言用語解説

用語読み⽅ひと言で何?ざっくり解説
GNU「グヌー」“自由ソフト”の旗印GNU = “GNU’s Not Unix” の再帰略語。Linux カーネルと組み合せて OS が完成。
プレースホルダ「あとで値を入れる空席」例:%s${S_ENTRY} 。実行時に実データと置換される。
後勝ちルール「あとがち」同じ変数を後で再定義すると後が優先Makefile・シェルとも共通。.env → コマンド行上書きが代表例。
flush=True「フラッシュ トゥルー」ログを“即書き出し”モードバッファを溜めずに標準出力へ強制送信。Docker logs が欠ける問題を解消。
METRIC「メトリック」統計用の専用ログ行METRIC spr=0.05 lot=0.001 のような計測データだけを 10 秒ごとに吐く仕組み。
抽象値「ちゅうしょうち」“直接バレても困らない加工値”例:実残高でなく 正規化 した 0 〜 1 の値をログへ。安全に共有・統計できる。
I/O / DB I/O「アイオー」入出⼒/データベース操作CPU ではなくディスク・ネットの遅延がボトルネックか判断するときに計測。
${VAR}「ダラー ブイエーアール」bash の変数展開envsubst でテンプレを実値に差し替える記法。
クオートする「クオート」文字列を ' '" で囲む数値をクオートすると JSONDecodeError の原因になるので要注意。
curl「カール」HTTP を叩くコマンド`curl -s
tail -F「テイル エフ」“ファイルを追尾+切替え検知”ログローテでファイル名が変わってもストリームが途切れない。
tail × flushtail -F + flush=True の合わせ技出し忘れ&読めないを同時に無くす王道セット。
JSON 生成エラーJSONDecodeError / ValueErrorほぼ「数値をクオートした」「カンマ抜け」の 2 大原因。
git revert「ギット リバート」特定コミット を“打ち消す”新コミット安全な巻き戻し。git revert HEAD~1 で 1 つ前を取り消し ⇒ 10 分ロールバック など即時復旧に使う。

最後まで聞いてくださってありがとうございました。
それではまた次回の放送でお会いしましょう。よだかでした。

-Bot, mmnot, 開発ログ