Bot プログラミングスキル 環境構築・インフラ 開発ログ

🛠️開発記録#226(2025/5/14)トレードロジック以外の基礎部分♻️セクション5:取引ループ run_loop() の正体とは?

― Botが市場と向き合い続ける「戦場のメインルーチン」

前回の記事までで、Botがどのように起動し、設定を読み込み、環境を整えてスタートラインに立つかを見てきました。
いよいよ今回は、Botが実際に市場で注文を出し、監視し、ポジションを検出し、損益を通知し、危険時には撤退するという一連のロジック――その「本番ループ」の中身を読み解いていきます。


🚀5.1 run_loop() とは?

run_loop() は、Botが稼働中に何度も繰り返し実行している「取引サイクルの心臓部」です。

この中でBotは以下のことを順に行っています:

  1. 板情報(orderbook)の取得と更新
  2. 現在のポジションと未実現損益の確認
  3. スプレッド判定に基づくエントリー可否の判断
  4. オーダーの発注と埋まりの監視
  5. Slackへの通知
  6. 条件による早期停止(ガード)処理

🧩5.2 全体フローを俯瞰してみよう

まずは全体の流れを図でつかみましょう:

🧭【図解】run_loop の主な処理フロー

flowchart TD
    A["WebSocketで板情報取得"] --> B["RESTでポジション確認"]
    B --> C["未実現損益を計算"]
    C --> D{"DD条件に抵触?"}
    D -- Yes --> E["SlackにDD通知 → return"]
    D -- No --> F["スプレッド判定"]
    F --> G{"スプレッド条件OK?"}
    G -- No --> H["何もしない → 次ループへ"]
    G -- Yes --> I["指値注文(Bid/Ask両サイド)"]
    I --> J["wait_for_fill()で監視"]
    J --> K["Filled or Cancel → Slack通知"]
    K --> L["次のサイクルへ"]

🔍5.3 処理ステップの解説

🔸① 板情報の取得(WebSocket)

orderbook = await ws.subscribe("orderbook.1.BTCUSDT")

Bybitの WebSocket v5 を使って、板情報(BID/ASKのリアルタイム更新)を受信。
Python側では、非同期で常に最新の bid, ask を保持し続けます。


🔸② ポジション情報の取得(REST)

position = await rest.get_positions()

ここで、現在のポジションや未実現損益(Unrealized PnL)を取得。
さらに Realised と合算して「現在の損益状態」を把握します。


🔸③ DDガード(最大損失監視)

if realised + unreal <= -6:
    send_slack("🚨 DD Hit: 停止します")
    return
  • 最大損失が一定額(例:–6 USDT)を超えたら 即座にSlack通知&ループ離脱
  • コンテナは exit(0) → 自動再起動(unless-stopped)へ

✅ この仕組みがあることで、「損失が出てもBotが止まらない」事故を防げる


🔸④ スプレッド判定(エントリー判断)

spread_pct  = (ask - bid) / bid
spread_tick = (ask - bid) / 0.1
  • スプレッドが十分に開いているか(=有利な状況か)を2つの基準でチェック:
    • パーセンテージで見る spread_pct
    • ティック数で見る spread_tick(例:0.1ドル単位)
if spread_pct <= S_ENTRY or spread_tick < 1 or notional > 250:
    continue  # 条件を満たさないときは何もしない

🔸⑤ 指値注文 → 埋まりの監視

await send_limit_order(side="Buy", price=bid - tick)
await send_limit_order(side="Sell", price=ask + tick)
await wait_for_fill()
  • BID/ASKの内側3ティック以内に指値注文を置く
  • wait_for_fill() で一定時間監視
  • Fillされたら利益/キャンセルされたらロスレス撤退

🔸⑥ Slackへの通知(軽量フォーマット)

send_slack("🟢 Filled Buy/Sell: PnL=+0.42")
  • 実際の通知内容は 余分な情報を削った軽量版
  • depth, fee, gross などの詳細は省略し、視認性を最優先

🔸⑦ フェイル時の対応・Graceful Exit

  • 連続失敗3回、あるいは サイクル数が一定数を超えた場合は :checkered_flag: をSlackに送り、Botは静かに終了

🧵まとめ:run_loopはBotの「戦術AI」そのもの

このループはただの繰り返しではありません。
市場の状態を観察し、リスクを評価し、タイミングを見て注文し、問題があれば即座に撤退する――

🔸まさに「仮想通貨市場という戦場における、リアルタイム思考と行動の連鎖」です。

-Bot, プログラミングスキル, 環境構築・インフラ, 開発ログ