初回公開:2025‑04‑01 / 最終更新:2025‑04‑24
前回の記事に引き続き、今回も仮想通貨botの開発状況をまとめていきます。
本記事では「暗号通貨のパンプ&ダンプスキームの検出」に関する論文をベースにbot開発の過程をまとめていきます。
Detecting Crypto Pump-and-Dump Schemes: A Thresholding-Based Approach to Handling Market Noisehttps://t.co/ctCJEV1MBs
— よだか(夜鷹/yodaka) (@yodakablog) March 22, 2025
✅ 1. 運用ルールの確立
- Botの稼働スケジュール設計
- 障害発生時の対応フロー策定
- 異常検出やリスク回避の優先順位決定
✅ 2. 最終パフォーマンスチェック←今ここ
- シミュレーション結果と実運用結果の比較
- 取引成功率、利益率、エラー率の再評価
- 調整が必要なパラメータの特定
✅ 3. デプロイ後の安定性確認
- Podの状態、リソース使用率の監視
- APIエラーやデータ欠損の確認
- Slack通知やログ記録の精度確認
✅ 1.運用ルールの確立 (Botの稼働スケジュールや障害対応フローの策定)
✅ 2.最終パフォーマンスチェック (シミュレーションと実運用の比較検証)
✅ 3.デプロイ後の安定性確認 (サーバー監視とログの確認)
次のステップとして、2.最終パフォーマンスチェック(シミュレーションと実運用の比較検証)に進みます。
目的
- シミュレーション結果と実運用結果を同じ指標で比較し、再現性を確認
- ズレの要因を特定して パラメータ/ロジックを最終調整
- 本番リリース前に “数値で安心” を取る
0. イントロ
前回(part.23)では 「暗号通貨のパンプ&ダンプスキーム検出」 の論文に基づき、検知ロジックと運用ルールを実装しました。今回の part.24 では、その 検知 Bot を例に「バックテスト vs. 実運用」のパフォーマンスを数値で突き合わせ、最終調整へ進む手順を解説します。
1. ステップ概要
準備 → 比較 → 調整 → 次フェーズ CSV 生成 指標の差確認 パラメータ修正 監視&デプロイ
2. データ準備
2‑1 ファイル構成
results/ ├── backtest_result.csv # バックテスト取引ログ ├── live_trade_log.csv # 実運用ログ └── performance_comparison.py# 比較スクリプト(§3)
2‑2 CSV 列仕様
| timestamp | symbol | side | size | price | pnl | balance |
|---|
2‑3 backtester_export.py(全文:バックテスト結果を保存)
#!/usr/bin/env python3
"""
backtester_export.py
────────────────────────────────────────────────────────
バックテストで得た取引ログ (list[dict] など) を
CSV ファイル `./results/backtest_result.csv` として保存するユーティリティ
❏ 使い方
$ python backtester_export.py
└─ ./results/backtest_result.csv が生成される
"""
from pathlib import Path
from datetime import datetime, timedelta
import pandas as pd
import random
# ① ダミーログを用意 ※実際はここをバックテストの生ログに置き換える
trade_log = []
base_time = datetime(2025, 3, 30, 10, 0, 0)
balance = 10_000 # スタート残高 USDT
for i in range(50):
ts = base_time + timedelta(minutes=i * 30)
side = 'buy' if i % 2 == 0 else 'sell'
price = 70_000 + random.uniform(-300, 300)
size = 0.01
pnl = random.uniform(-30, 50)
balance += pnl
trade_log.append({
"timestamp": ts.strftime("%Y-%m-%d %H:%M:%S"),
"symbol" : "BTCUSDT",
"side" : side,
"size" : size,
"price" : round(price, 2),
"pnl" : round(pnl, 2),
"balance" : round(balance, 2)
})
# ② DataFrame へ変換
df = pd.DataFrame(trade_log)
# ③ 保存ディレクトリを保証して CSV 出力
out_dir = Path("./results")
out_dir.mkdir(parents=True, exist_ok=True)
csv_path = out_dir / "backtest_result.csv"
df.to_csv(csv_path, index=False)
print(f"✅ バックテスト結果を保存しました → {csv_path}")
2‑4 live_log_export.py(全文:実運用ログを整形)
#!/usr/bin/env python3
"""
live_log_export.py
────────────────────────────────────────────────────────
Bot が吐いたテキストログ (./logs/live_trade.log) をパースし、
./results/live_trade_log.csv に整形保存するユーティリティ。
❏ 想定ログフォーマット
[YYYY-MM-DD HH:MM] Trade executed: SYMBOL SIDE SIZE @ PRICE, PnL: PNL, Balance: BAL
"""
from pathlib import Path
import re
import pandas as pd
# ① 入出力パス
log_path = Path("./logs/live_trade.log")
out_dir = Path("./results")
out_dir.mkdir(parents=True, exist_ok=True)
csv_path = out_dir / "live_trade_log.csv"
# ② 正規表現パターン
a = (r"\[(?P<ts>.*?)\] Trade executed: "
r"(?P<sym>\w+) (?P<side>\w+) (?P<size>[\d.]+) @ (?P<price>[\d.]+), "
r"PnL: (?P<pnl>-?[\d.]+), Balance: (?P<bal>[\d.]+)")
pat = re.compile(a)
rows = []
with log_path.open() as f:
for line in f:
if (m := pat.search(line)):
rows.append(dict(
timestamp=m["ts"], symbol=m["sym"], side=m["side"],
size=float(m["size"]), price=float(m["price"]),
pnl=float(m["pnl"]), balance=float(m["bal"])))
if not rows:
raise RuntimeError(f"❌ パースできる行が見つかりません: {log_path}")
pd.DataFrame(rows).to_csv(csv_path, index=False)
print(f"✅ 実運用ログを CSV に変換しました → {csv_path}")
簡易チェックリスト
- 列構成:
timestamp, symbol, side, size, price, pnl, balance- 欠損ゼロ:
df.isnull().sum()- 重複ゼロ:
df.duplicated().sum()
3. 比較スクリプト performance_comparison.py
import pandas as pd
# ------------------------------------------------------------
def load_data():
"""バックテストと実運用 CSV を読み込む"""
bt = pd.read_csv('./results/backtest_result.csv')
lv = pd.read_csv('./results/live_trade_log.csv')
return bt, lv
# ------------------------------------------------------------
def calculate_metrics(df):
"""主要 4 指標を返す"""
n = len(df)
win = df[df['pnl'] > 0]
w% = len(win) / n * 100 if n else 0
pnl = df['pnl'].sum()
dd = (df['balance'].cummax() - df['balance']).max()
return {
'trades' : n,
'win_rate' : round(w% , 2),
'pnl_total' : round(pnl, 2),
'max_drawdown' : round(dd , 2)
}
# ------------------------------------------------------------
def compare():
bt, lv = load_data()
bt_m = calculate_metrics(bt)
lv_m = calculate_metrics(lv)
print("\n📈 最終パフォーマンス比較")
print(f"{'指標':<15} | {'シミュレーション':<12} | {'実運用':<12}")
print("-" * 46)
for k in bt_m:
print(f"{k:<15} | {bt_m[k]:<12} | {lv_m[k]:<12}")
# ------------------------------------------------------------
if __name__ == "__main__":
compare()
4. 実行 & 出力例
$ python performance_comparison.py
📈 最終パフォーマンス比較 指標 | シミュレーション | 実運用 ---------------------------------------------- trades | 128 | 116 win_rate | 58.59 | 51.72 pnl_total | 2650.5 | 1780.1 max_drawdown | 420.25 | 690.8
5. 差分を読む:原因 × 改善
| 指標 | 代表的原因 | 代表的改善策 |
|---|---|---|
| trades | Bot 停止 / スケジュール漏れ | スケジューラ確認・例外復帰処理 |
| win_rate | 遅延 / トリガー劣化 | スリッページ補正・閾値再設定 |
| pnl_total | 手数料 / 成行偏重 | 指値+監視発注 / 多段利確 |
| max_drawdown | SL 設計が甘い | ATR 等で動的 StopLoss |
6. 最終調整サンプル
# config.yaml before → after RSI_OVERSOLD : 30 → 35 RSI_OVERBOUGHT : 70 → 65 ATR_THRESHOLD :100 → 80 STOP_LOSS_PERCENT :4.2 → 3.0 TAKE_PROFIT_PERCENT:6.8 → 5.5
# トレンドフィルターを追加 df['ma_fast'] = df['close'].rolling(5).mean() df['ma_slow'] = df['close'].rolling(20).mean()
手順
- 調整を反映 → 再バックテスト (
backtester_export.py) backtest_result.csvを更新performance_comparison.pyを再実行 → 数値確認
7. まとめ & 次のアクション
- 比較 → 評価 → 調整 のステップ 2 を完了
- 指標が許容範囲なら 監視設計 (Slack 通知・Pod 監視など) を実装
- 次回 part.25 は デプロイ後の安定性確認 を掘り下げます。
📌 フローを自動化する場合は CI で CSV 出力 → 比較 → Slack レポートを回すと便利です。
-
-
開発記録#163(2025/4/2)「論文ベースのbot開発フローpart.25 デプロイと運用安定化」
続きを見る
👇ラジオで話したこと
こんにちは、Yodakaです。
今回のラジオでは、「仮想通貨Botって、作った通りにちゃんと動いてるの?」というテーマでお話します。
というのも──Botを動かし始める前に「シミュレーションで勝ってた戦略」が、本番環境でもちゃんと勝ってるのか?って、確認しないと怖いですよね。
これを 「最終パフォーマンスチェック」 と呼んで、Bot開発の第2ステップに位置づけています。
🧩 概要:バックテスト vs 実運用の比較
Botって、最初は「過去のチャートでどう動くか」っていう**シミュレーション(バックテスト)**を通して設計します。でも実際にマーケットで動かすと──
- サーバー落ちてた!
- 注文通ってなかった!
- 約定(=注文が通ること)してなかった!
……なんてことが、しょっちゅうあるんですね。
だから「シミュレーション通りに動いてたのか?」をあとから数字で見比べるのが超重要になります。
🗂️ 1. データを準備する
まずは、**「シミュレーション結果」と「実運用の結果」**を、それぞれCSVファイルという表形式のデータにまとめます。
backtest_result.csv(バックテストの記録)live_trade_log.csv(本番Botのログ)
この2つができれば、あとはPythonでスクリプトを1本書いて比べるだけ。
🧪 2. どんな指標で比べるの?
比較する項目は、主に以下の4つです:
| 指標名 | 意味 |
|---|---|
| trades | トレードの回数(Botが何回売買したか) |
| win_rate | 勝率(利益が出た割合) |
| pnl_total | 合計の利益(損益) |
| max_drawdown | 最大ドローダウン(口座が一番減った瞬間) |
例えば「シミュレーションでは120回トレードしてたのに、実運用では80回しかしてない」とか、「勝率が7割だったのに実運用では5割しかない」など、ズレをあぶり出します。
🧰 3. 比較スクリプトの一部(ざっくり)
def calculate_metrics(df):
total = len(df)
wins = df[df['pnl'] > 0]
return {
'trades': total,
'win_rate': len(wins) / total * 100,
...
}
こんな感じで、「勝ってるトレードの数」や「トレード回数」をカウントして指標を作ります。
⚠️ 4. ズレの原因と対策
ズレが出たときの原因と、それに対して何を調整すればいいかの例を紹介します。
| ズレ内容 | よくある原因 | 対策 |
|---|---|---|
| トレード数が少ない | Botが止まっていた | ログで停止原因を調査 |
| 勝率が下がってる | 市場の動きが予想外だった | スリッページ補正を導入 |
| PnLが低い | 注文が成行で高コスト | 指値で発注するよう修正 |
| DDが大きい | 損切りラインが甘い | StopLossを強化 |
🔧 5. 最後にやること(最終調整)
もしズレがあれば、以下のようにパラメータを微調整します:
- RSIの基準値を見直す
- 利確や損切りの幅を変える
- トレンドフィルター(移動平均線)を導入する
そして、またバックテストして改善したかを確認。
これを**「数値で検証 → 修正 → 再検証」**とループして、精度を高めていきます。
✅ まとめ
最終パフォーマンスチェックは、言ってみれば「Botの健康診断」です。
頭の中で「勝てる!」と思って作った戦略でも、本番のマーケットは予測不能なことばかり。
だからこそ、「ズレてないか?」を数値で確認する習慣が大事です。
次回は、このBotをいよいよ「本番環境で安定稼働させる」ためのステップ──モニタリングと通知の整備についてお話しします。
ではまた、次回の放送でお会いしましょう!