Bot mmnot 開発ログ

🛠️開発記録#219(2025/5/13)MMbot開発ログ23「PostOnly 固定で“手数料負け”を根絶するまで ― MMBot パラメータ・ハードニング」

2025年5月13日

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

0. はじめに

前回は “可観測性” をテーマに、メトリクス取得とログ設計を整えました。
今回は 「手数料を負け筋から勝ち筋へ反転させる」 が主眼です。
データを収集しながらMaker 固定 に到達するまでの試行錯誤と、
安全にデプロイするためのシェル改善を共有します。


1. 到達点(公開版サマリ)

項目ステータス
注文方式PostOnly 100 %(Maker リベート –0.02 %)
ループ間隔5 s(旧 8 s:板追従性向上)
エントリー判定spread% × tick 数 の複合条件
安全装置DD ガード 3 USD / minQty 自動補正
デプロイDocker Compose + Poetry / ShellCheck で静的解析
現フェーズ24 h 実弾ミニマム運用で Maker 比率を監視
NextLot 拡張 → 動的スプレッド閾値の自動調整

2. 今回“新しく”手を入れたポイント(前回と非重複)

#施策目的・効果備考
1PostOnly 強制フラグFORCE_POST_ONLY=trueすべての約定を Maker に固定し、リベートで手数料を相殺CLI ↔ env ブリッジでオンオフ自在
2スプレッド閾値の逆算Maker リベート込みで “最低勝てる幅” を理論値から設定具体値は非公開
3tick 判定パラメータ化 (TICK_THR)板が詰まった 1 tick ノイズで発注しない本番ネットの板厚でチューニング
4minQty 自動取得取引所仕様更新に負けない起動ロバスト性REST 1 call、0.3 s で完了
5ShellCheck + set -euエントリポイントのシェル事故をゼロにCI で毎プッシュ実行中

3. “Maker 固定” を実現するパラメータ設計フロー

  1. 手数料を先に差し引く
  2. 残る利幅 = 目標スプレッド
  3. tick 数で現実幅を検証
flowchart LR
  Fee["Taker 手数料<br>0.055 % ×2"] -->|逆算| Width["必要スプレッド%"]
  Width --> Tick["Tick 数に換算"]
  Tick --> Entry["エントリー閾値 (spread% & tick)"]

Maker リベート(-0.02 %×2)を踏まえないと、
「広がったつもりで実は負けていた」罠にハマります。


4. デプロイを安全にするシェル Tips

チェック項やったことWhy
未定義変数エラーset -eu 追加“typo 1 文字”で即クラッシュ→事故前に検知
動的フラグ挿入${POST_FLAG:+"$POST_FLAG"}空文字なら丸ごと引数を省略
CI 静的解析shellcheck entrypoint.shコンテナビルド前にヒューマンエラー排除

5. 今回の学び

  • Maker リベートは“戦略”ではなく“前提条件”
    → 取れないなら MM 戦略を名乗るべきではない、と再認識。
  • 閾値は「理論 → 実観測 → 再キャリブレート」のループで締まる
    → データ無しのチューニングは時間の浪費。
  • シェルは小さくてもクリティカルパス
    set -eu と ShellCheck だけで本番落ちが激減。

6. 次の一手

  1. Lot 拡張 → スリッページ計測
  2. 動的 s_entry(ボラティリティ依存)実装
  3. Maker/Taker 統計を Slack 集計ボットで自動可視化

7. おわりに

エッジを伏せつつ「何を考え、どこを変えたか」は公開できる──
公開することを通して、自分の思考と戦略を再確認できる──
Bot 開発は “情報戦” と “再現性” の両立が難しいですが、
測って・固めて・また測る の繰り返しが遠回りのようで一番速い。

本記事は技術共有を目的としたものであり、投資助言ではありません。
実売買はご自身の判断と責任で。

👇ラジオで話したこと

MMbot開発ログ23「PostOnly 固定で“手数料負け”を根絶するまで──MMBot パラメータ・ハードニング」


「今日は“Maker リベートで勝ち筋を作る”がテーマ。PostOnly=板に注文を置く側に固定し、手数料を“もらう”側へ反転させます。では、どんなパラメータを触り、どこに落とし穴があったのか? ゆるっと深掘りしていきましょう!」


1│そもそも PostOnly・Maker とは?

  • 取引所の手数料モデル
    • Maker (板に流動性を供給)=多くの取引所でマイナス手数料、Bybit だと –0.02 % が典型
    • Taker (板の既存注文を食う)=0.05 % 前後の支払い側。
  • PostOnly フラグを付けると「板に刺さらず即約定しそうならキャンセル」という安全弁になり、約定は 100 % Maker

★ワンフレーズ:
「PostOnly = Maker 固定スイッチ」


2│今回いじった5つのポイント

#施策ねらい実装メモ
1FORCE_POST_ONLY=trueMaker100%でリベート確保CLI と .env の両方で切替可
2スプレッド閾値の逆算「Makerリベート – Taker手数料 ×2 > 0」を方程式化理論最小値=勝てる幅を先に算出
3TICK_THR パラメータ板が詰まった 1tick ノイズで発注しないtick は「最小価格単位」
4minQty 自動取得取引所の最小ロット更新で 404 を回避起動時に REST を1回だけ呼ぶ
5Shell ハードニングset -eu で typo 即停止・ShellCheck で lintShellCheck は CI に 1 行で追加可

3│パラメータ設計フロー

  1. 手数料を先に差し引く
    • Taker: +0.055 % ×2 Maker: –0.02 % ×2 👉 最低でも 0.07 % 稼がないと赤字
  2. 目標スプレッド% → tick 数へ換算
    • 例:BTCUSDT の tick=0.1 USDT 👉 0.07 % =約 70 $/BTC → 700 ticks
  3. spread_pct >= X && tick >= Y複合判定へ落とす。

「Maker 戦略は“儲ける”前に“負けを消す”計算から」

① “前提のおさらい”

「まず、取引には必ず“手数料”が付いて回ります。
買いでも売りでも、板に置いた指値が“受け身で約定”すれば

‘メーカー(Maker)手数料’で –0.02 % のリベートが貰える。
逆に、こちらから成行で突っ込む ‘テイカー(Taker)’ だと
+0.055 %×2回ぶん、合計約 +0.11 % を払う――
ここがスタートラインです。」**


② “理論上の最低ライン”を電卓で弾く

「ということは、
メーカーで2回約定 → –0.04 % が手数料で返ってくる。
テイカーで2回 → +0.11 % 取られる。
その差し引きで 約 +0.07 % 以上の利幅を取らないと、
トータルで赤字、という計算ですね。」**


③ “%”を“ティック数”に置き換える

「ところが板は “パーセント” じゃなく ‘ティック’ で動きます。
いま BTC/USDT のティックは 0.1 ドル。
1 BTC が 100 000 ドルとすると、0.07 % は 70 ドル に相当。
70 ドル ÷ 0.1 ドル = 700 ティック。
つまり “700 ティック以上開いた瞬間じゃないと負ける”
-- これが数字の意味合いです。」


④ “複合判定”でノイズをカット

「そこでプログラムでは、
spread_pct >= X かつ tick >= Y ――
パーセント条件とティック条件を両方クリアした瞬間だけ
&&(アンド条件)で発注します。
パーセントは利幅を、ティックは板の ‘厚み’ を保証する。
2つのフィルターを通すことで “手数料負け” を根絶しよう、
という狙いです。」**


⑤ まとめ & 次のセグへブリッジ

「要は 『まず手数料を払う前提で利幅を逆算、
その数字をパーセントとティックの “二重ゲート” に落とす』

これが マーケットメイク Bot の基本設計 です。
では実際の板でどうチューニングしたか――
次のパートで実測ログを見ながら解説します!」


4│デプロイ周りの安全装置

  • set -eue : error-on-fail / u : undefined 変数エラー
  • ShellCheck で静的解析(CI 失敗ならビルド拒否)
  • 動的フラグ${POST_FLAG:+"$POST_FLAG"}
    • 変数が空なら引数自体を削る Bash テンプレート技法。
  • Poetry + Docker Compose
    • make mainnet-loop
      1. .env.prodenvsubst でテンプレに流し込み
      2. PostOnly フラグ付きでコンテナ起動。

5│6 時間実弾ミニマムテストの結果

指標コメント
Lot0.0001 BTC資金リスクを極小化
ループ間隔5 s板追従性 ↑
Maker 比率100 %PostOnly 成功
Net PnL+0.27 USDT手数料差し引き後でも黒字
最大 DD–0.9 USDTDD_GUARD=3 で未発火

静かなログmake logs-warnWARN 0 行、「何も起きない=想定どおり」の確認。


6│今日の学び

  1. 「Maker リベートは“前提条件”」──取れない環境なら戦略を再考せよ。
  2. 理論値 → 実データ → 再調整 のループが最短。
  3. シェルは小さくても本番クリティカル──lint と set -eu で事故率激減。

7│次の一手

  • Lot 拡大+スリッページ測定
  • ボラティリティ連動 s_entry の自動化
  • Maker/Taker 比率を Slack Bot で日次レポート

▽ おまけコーナー

  1. 「Maker と Taker、言い分の違い」
    • Maker は「店側」、Taker は「来店客」。
    • 流動性コスト vs 機会費用のトレードオフ。
  2. set -eu って読み方?
    • 「セット・ハイフン・イー・ユー」── uundefined.
  3. ShellCheck が教えてくれた3つの凡ミス
    • 変数名 typo
    • "$@" を忘れて引数ロスト
    • echo に未クオート JSON → パース崩壊

「lint はうるさいけど、“今怒られるか、明朝4 時に怒られるか” の違い」


「測って固めて、また測る。遠回りのようで最速――これがマーケットメイク Bot の醍醐味です。次回は可視化と動的パラメータで、さらに一段ギアを上げていきます。それでは、また!」

-Bot, mmnot, 開発ログ