トレーディングボット用VPSで本当に重要なこと
トレーディングボットに必要なのは、systemdの再起動設定、UTC時刻、APIキー保護、heartbeat監視です。systemdは10秒間に5回で再試行を諦めるため、設定と遅延の限界を確認します。
トレーディングボットにVPSが必要とするもの
トレーディングボット用のVPSは、4つの点で評価します。プロセスが停止した後に復旧するか、時刻が正確か、API(application programming interface)キーを盗まれにくくできるか、停止したときに把握できるかです。個人向けボットでは、処理速度の優先度は大幅に低くなります。注文経路で時間がかかるのは、ホスト上のPythonではなく、ブローカーとホストからブローカーまでの距離だからです。
これはエンジニアリングガイドです。ここに金融に関する助言はありません。取引戦略についても説明しません。
稼働時間は販売ページの数値ではなく、再起動の管理です
世界中のすべてのホストが、稼働率99.9パーセントをうたっています。この数値が示すのはハイパーバイザーであり、botではありません。botは未処理の例外、再接続しないwebsocket、またはOOM(out of memory)killerによって停止します。その間もサーバー自体は稼働し続けます。したがって重要なのは、プロセスが終了した後の10秒間に何が起きるかです。
botをsystemdサービスとして実行し、再起動をinit systemに任せます。unit fileなら6行で設定できます。
[Unit]
Description=Trading bot
After=network-online.target
Wants=network-online.target
StartLimitIntervalSec=0
[Service]
Type=simple
User=bot
WorkingDirectory=/opt/tradingbot
EnvironmentFile=/etc/tradingbot/api.env
ExecStart=/opt/tradingbot/venv/bin/python -m tradingbot
Restart=always
RestartSec=10
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
ReadWritePaths=/var/lib/tradingbot
[Install]
WantedBy=multi-user.targetStartLimitIntervalSec=0は見落とされがちな行です。デフォルトではsystemdは10秒間に5回再起動すると処理を諦め、unitをfailed状態のまま永続的に残します。これは03:00に発生してほしくない動作です。0に設定するとレート制限が無効になり、crash-loopするbotは停止せずに再試行を続けます。RestartSec=10は、このループによってexchangeへの再接続が過剰に発生するのを防ぎます。
信頼する前にファイルを検証し、その後で起動します。
sudo systemd-analyze verify /etc/systemd/system/tradingbot.service
sudo systemctl daemon-reload
sudo systemctl enable --now tradingbot
systemctl status tradingbotenableは再起動後も設定を保持する部分です。kernelの更新では再起動が必要になります。botがひそかに停止し続けていないか確認するには、systemdに再起動回数を問い合わせます。
systemctl show tradingbot -p NRestarts
journalctl -u tradingbot --since "24 hours ago" | tail -501週間後のNRestarts=0は、正常なbotを示します。NRestarts=812は、一晩中再接続を繰り返すプロセスで取引していたことを意味します。日次レポートなどのスケジュールジョブ用timerを含むunit fileの全体構成については、systemdサービスとしてプログラムを実行するで説明しています。
クロックを UTC に設定し、同期されていることを確認する
取引所 API はタイムスタンプでリクエストに署名し、許容範囲外のリクエストを拒否します。許容範囲は5秒以下であることがよくあります。クロックがずれると、認証失敗に見えるエラーが発生します。そのため、時刻を確認する前に何時間もキーをローテーションすることがあります。Binance 形式の API では、メッセージは文字どおり次のとおりです: Timestamp for this request was 1000ms ahead of the server's time。
サーバーを UTC に設定します。ローカルタイムゾーンでは夏時間への切り替えによる時刻のジャンプが発生し、取引セッションの途中で影響する可能性があります。
sudo timedatectl set-timezone UTC
timedatectlUbuntu には systemd-timesyncd が付属しています。これは SNTP(Simple Network Time Protocol)クライアントです。ログ用途には十分ですが、数ミリ秒以内の精度を維持する必要がある用途には不十分です。1台のサーバーをポーリングするだけで、クロックを継続的に調整しないためです。代わりに chrony を使用します。
sudo apt update && sudo apt install -y chrony
sudo systemctl enable --now chrony
chronyc tracking
chronyc sources -vchronyc tracking から読み取る行は System time です。たとえば System time : 0.000031415 seconds fast of NTP time のようになります。数ミリ秒未満であれば正常です。Leap status : Not synchronised と表示される場合、chrony はまだサーバーに到達していません。通常は、外向きの UDP 123 がブロックされています。1分待ってから、ファイアウォールのルールを変更する前に再度確認します。
コピーされる場所に API keys を置かない
漏えいした exchange key は、漏えいした SSH key より危険です。withdrawal permission があると、即座に資金の流出につながるためです。リスクの大半は、2つの習慣で抑えられます。
まず、bot key に withdrawal permission を決して付与しないでください。exchange が対応している場合は、key をサーバーの IP address にバインドしてください。盗まれた key をほぼ無価値にできる、最も重要な対策です。
次に、secret を code directory の外に置いてください。/opt/tradingbot 内のものは、遅かれ早かれ git repository または backup archive に入ります。systemd だけが読み取る、root 所有の file に保存してください。
sudo install -d -m 750 -o root -g bot /etc/tradingbot
sudo install -m 640 -o root -g bot /dev/null /etc/tradingbot/api.env
sudo nano /etc/tradingbot/api.envこの file には、引用符も export もない plain KEY=value lines を記述します。group bot を設定した mode 640 では、service user だけが読み取ることができ、他のユーザーは読み取れません。sudo -u bot cat /etc/tradingbot/api.env で確認し、その後、別のユーザーでも確認してください。この場合は Permission denied が失敗する必要があります。
bot 自体を root または login user として実行しないでください。ログイン用の shell と home directory を持たない system account を作成します。
sudo useradd --system --shell /usr/sbin/nologin --home-dir /var/lib/tradingbot --create-home botこれらの flags の意味と、ProtectSystem=strict が実際にどこまで制限するかについては、非特権ユーザーとしてサービスを実行するで説明しています。SSH keys と firewall を含む、その他のサーバーの基本設定は、新しい VPS で最初の10分間に行う設定で扱います。
ブローカーより先に停止を把握する
systemctl status はプロセスが実行中であることを示します。ボットが動作していることまでは示しません。停止した websocket への再試行ループでプロセスが停止していても、systemd が実行できるすべてのチェックには合格します。
代わりにハートビートを使用します。Uptime Kuma にはプッシュ監視機能があります。これは、ボットが一定間隔で URL を呼び出すことを想定し、呼び出しが届かなくなったときにアラートを送信します。ボットが稼働していることを確認できる処理(正常な market data の読み取りなど)の後、メインループの最後にこの呼び出しを追加します。
curl -fsS "http://monitor.example.com:3001/api/push/YOUR_TOKEN?status=up&msg=loop_ok"通常の揺らぎでページャー通知が発生しないように、監視間隔はループ時間のおよそ2倍に設定します。監視対象のボットと同じ障害で停止すると何も報告できないため、監視はボットとは別のサーバーで実行します。セットアップ方法は、Uptime Kuma を使用したセルフホスト型ステータス監視で説明しています。
ディスクアラートも追加します。詳細なログを書き込むボットは数週間で root ファイルシステムを使い果たします。ディスクが満杯になると、ネットワーク呼び出しではなくデータベースへの書き込みが停止するため、症状が分かりにくくなります。journalctl --vacuum-time=14d と /etc/systemd/journald.conf 内の SystemMaxUse= 行によって、journal のサイズを制限できます。
正直なところ: レイテンシの大部分はホストによるものではありません
ここで、取引向けVPS製品の市場は技術的な話から離れます。マーケティングページは1ミリ秒未満の数値を示し、約定を左右するのはホストであるかのように説明します。しかし、ほぼすべての個人向けbotではそうではありません。
注文は、botから取引所またはbrokerのエンドポイントまで、public internetを経由して移動します。この経路は、物理的な距離と、利用するproviderと相手側providerの間のpeeringに大きく左右されます。FrankfurtのサーバーがTokyoのエンドポイントと通信する場合、CPUがどれほど高速でも、往復でおよそ250ミリ秒かかります。さらにbroker自身のシステムがキュー処理、リスクチェック、rate limitを追加します。個人向けアカウントでは、通常これらは数十ミリ秒から数百ミリ秒です。
推測せずに測定してください。curlは、実際のエンドポイントへの接続時間と最初のバイトを受信するまでの時間を報告します。
curl -s -o /dev/null -w 'dns=%{time_namelookup}s connect=%{time_connect}s ttfb=%{time_starttransfer}s\n' \
https://api.kraken.com/0/public/Time
mtr -rwzc 100 api.kraken.com契約する前に、候補のサーバーからこれを実行してください。connectが0.180秒なら、大陸の選択を誤っており、修正する価値があります。connectが0.004秒で、ttfbが0.140秒なら、残りの遅延はbrokerの処理によるもので、ホストを変更しても改善しません。
では、ホストが重要になるのはいつでしょうか。venueとcolocationまたはcross-connectしており、キュー内の順位を競う場合です。これは別の予算が必要な、別のビジネスです。また、自分のコードがボトルネックになっている場合も重要です。毎回のtickで履歴全体に対してindicatorを再計算するbotは、ループごとにCPUを200ミリ秒消費することがあります。これは自分で制御できる、実際のレイテンシです。より高速なサーバーを探す前に、ループをprofileしてください。
選ぶホストで重要なのは、地理的な位置、安定したネットワーク、そしてOOM killerが介入する余地がない十分なメモリです。2026年7月時点では、数百のsymbolをメモリに保持する単一戦略のPython botは、2 GBのRAMと2 vCPUで余裕を持って動作します。tick履歴をlocal databaseに保存する場合は、メモリを追加してください。
本番稼働前の簡易チェックリスト
systemctl is-enabled tradingbotはenabledを出力し、サービスはsudo reboot後も稼働します。chronyc trackingは、システム時刻のずれが数ミリ秒未満であることを報告します。- API key には取引権限だけを付与し、出金権限は付与しません。取引所が対応している場合は、IP allowlist も設定します。
sudo systemctl kill -s SIGKILL tradingbotでプロセスを停止すると、RestartSec以内に復旧します。- bot を意図的に停止すると、heartbeat monitor は1回の監視間隔以内に通知します。
- ログのサイズに上限があり、root filesystem には
df -hで十分な空き容量があります。
実資金を使う前に、取引所の sandbox または paper mode で1週間、全体を実行します。その1週間の間に、上記の項目はすべて少なくとも1回失敗します。これが1週間実行する目的です。
FAQ
取引ボットには低レイテンシまたはベアメタルサーバーが必要ですか?
同じ取引所で他の自動取引参加者と約定速度を競う場合に限り必要です。この場合、通常は汎用のVPSではなく、コロケーションを使用します。個人向けのボットでは、往復時間の大部分は地理的な距離とブローカー側の処理時間で決まります。そのため、APIエンドポイントに近いサーバーを選び、より高速な環境に料金を支払う前に curl と mtr で測定してください。
取引ボットにはどの程度のRAMとCPUが必要ですか?
単一戦略のボットの多くはネットワークがボトルネックで、イベント間はアイドル状態です。2026年7月時点では、2 vCPUと2 GBのRAMで、数百の銘柄を追跡するPythonボットを実行できます。ティック履歴をプロセス内に保持したり、ローカルデータベースを実行したりすると、メモリが制約になります。そのため、推測ではなく free -h とジャーナルでOOM killメッセージを監視してください。
取引所のAPIがタイムスタンプエラーでリクエストを拒否するのはなぜですか?
サーバーのクロックが取引所の署名受付時間の範囲を超えてずれています。通常は数秒のずれです。chronyをインストールし、chronyc tracking に小さな System time オフセットと同期済みのうるう秒ステータスが表示されることを確認してください。また、夏時間の変更で時刻がずれないよう、マシンをUTCに設定してください。API keyをローテーションしても、クロックの問題は解決しません。
ボットが停止しても気付かないまま一晩経過するのを防ぐにはどうすればよいですか?
Restart=always と StartLimitIntervalSec=0 を使用してsystemdの下で実行してください。これにより、クラッシュループが完全に停止せず、再試行を続けます。その後、各ループが正常に完了した時点でボットから送信するheartbeatを追加してください。再起動設定はプロセスを処理します。heartbeatは、プロセスが起動しているものの停止している状態を検出します。
ボットと監視を同じVPSで実行できますか?
実行できます。ただし、障害が発生した日に監視が誤った状態を示します。ボットを停止させる障害によって、監視も停止するためです。アラート処理は別のマシンに配置してください。理想的には、別のプロバイダーまたはリージョンを使用します。ボットのサーバーは、ボットとそのログ専用にしてください。