Build a Hyperliquid Webhook Alert System in 30 Minutes
By @CoinMarketMan - 10-Jul-2026
Hyperliquidウェブフック・アラートシステムを30分で構築する
ポーリングループは5分ごとに起動し、同じコホートデータを取得し、前回のスナップショットと比較して、何も変わっていないと判断する。その間に、Money PrinterコホートはETHでネットショートに転換し、$3,800レベル付近に清算クラスターが形成され、3頭のLeviathanがSOLで新規ロングを建てていた。次のポーリングが届く頃には、そのムーブはすでに織り込まれている。
ポーリングがデフォルトになっているのは、最もシンプルなパターンだからだ。インターバルを設定してエンドポイントを叩き、レスポンスを差分して終わり。しかしシンプルさには代償がある。レイテンシ、変化のないデータへの無駄なAPIコール、そして「前回と今回のリクエストの間に何か重要なことが起きたのではないか」という拭えない不安だ。ウェブフックはそのモデルを逆転させる。数分ごとに「何か変わったか?」と問い続ける代わりに、サーバーが変化の瞬間を知らせてくれる。
HyperTrackerのウェブフック配信は、Flow($799/月)とStream($1,999/月)のティアで利用できる。 URLを登録し、必要なイベントを設定するだけで、データ更新サイクル上でイベントが検知された瞬間に、署名付きJSONペイロードがエンドポイントにプッシュされる。 cronジョブも、レートリミットの計算も、データの鮮度切れウィンドウも不要だ。このガイドでは、ウェブフックの受信、ペイロードの検証、TelegramやDiscordへのアラートのルーティング、障害時の対処まで、セットアップの全工程を解説する。
ポーリング対プッシュ:実際に何を失っているのか
ポーリングのコストはレイテンシだけではない。典型的な実装の数字を考えてみよう。コホートメトリクスのエンドポイントを5分ごとにポーリングすると、1日288リクエスト、1アセット1エンドポイントで月約8,640リクエストになる。5アセットに広げると43,200リクエスト。オーダーフロースナップショットと清算リスクも加えると、モニタリングだけでPulseティアの月間50,000リクエストを使い切り、オンデマンドクエリの予算はゼロになる。
ウェブフックはこれを完全に解消する。関心のあるイベントだけを登録すれば、実際に何か変化があったときだけリクエストが発生する。閑散とした相場ではコストはゼロ。荒れた日にはペイロードが集中して届くが、そのひとつひとつには「変化なし」という処理して捨てるだけのレスポンスではなく、意味のある情報が含まれている。
レイテンシの差も重要だ。5分ポーリングでは最悪5分近い検知遅延が生じ、何も変化がないときもリクエストのオーバーヘッドを抱え続ける。ウェブフックなら、システムがリフレッシュサイクル上でイベントを検知した瞬間にペイロードが届き、無駄なコールは一切ない。コホートシフトや清算スパイクにおいては、ポーリングのオーバーヘッドをなくしてプッシュ配信を即座に受け取ることで、アーキテクチャはよりクリーンになり、反応ループはより速くなる。
ウェブフックエンドポイントのセットアップ
受信側はPOSTリクエストを受け付け、ペイロードを検証し、素早く200ステータスを返すHTTPサーバーにすぎない。エンドポイントはリトライロジックが起動しないよう、数秒以内に応答すべきだ。配信が失敗した場合は指数バックオフでリトライされる。障害が続くとウェブフックは一時停止され、ダッシュボードから再有効化するまで停止したままになる。
以下はExpressを使ったNode.jsの最小構成の受信サーバーだ:
import express from 'express';
import crypto from 'crypto';
const app = express();
app.use(express.json());
const WEBHOOK_SECRET = process.env.HT_WEBHOOK_SECRET;
function verifySignature(payload, signature) {
const expected = crypto
.createHmac('sha256', WEBHOOK_SECRET)
.update(JSON.stringify(payload))
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
app.post('/webhooks/hypertracker', (req, res) => {
const signature = req.headers['x-ht-signature'];
if (!signature || !verifySignature(req.body, signature)) {
console.error('Invalid webhook signature');
return res.status(401).json({ error: 'Invalid signature' });
}
// Acknowledge immediately, process async
res.status(200).json({ received: true });
// Handle the event
processEvent(req.body);
});
app.listen(3000, () => console.log('Webhook receiver on :3000'));
3点を押さえておきたい。第一に、署名の検証はオプションではない。これがなければ、エンドポイントURLを知った誰もが偽のペイロードを送り込める。HMAC-SHA256チェックにより、ペイロードがHyperTrackerから送られたものであることが保証される。第二に、処理の前に応答を返すこと。まず200を返し、その後ビジネスロジックを非同期で処理する。アラートのルーティングが遅いダウンストリームサービス(TelegramのAPI遅延、データベースの書き込み)にぶつかっても、ウェブフックの配信がタイムアウトしてリトライが発生するのを防げる。第三に、署名の比較にはtimingSafeEqualを使い、タイミング攻撃を防ぐこと。
ローカルサーバーの公開
開発中、localhostはインターネットから到達できない。トンネルを使って公開する:
# Option 1: ngrok
ngrok http 3000
# Option 2: Cloudflare Tunnel
cloudflared tunnel --url http://localhost:3000
生成されたHTTPS URLをコピーして、HyperTrackerのウェブフック設定に貼り付ける。本番環境では、安定したHTTPSエンドポイントを提供するクラウドプロバイダーにデプロイする。月$5のVPSでウェブフック受信サーバーには十分だ。
サブスクライブするイベントの選択
すべてのイベントがアラートを出す価値があるわけではない。通知チャンネルを台無しにする最速の方法は、ノイズで埋め尽くして何もかも無視するようになることだ。シグナル精度の高い少数のイベントから始め、量感をつかんでから広げていくといい。
Hyperliquidをモニタリングするトレーダーへの実践的な初期設定:
| イベントタイプ | 発火条件 | 重要な理由 |
| --- | --- | --- |
| cohort.shift | PnLコホートがあるアセットでネットロング/ショートに転換 | Money PrinterやSmart Moneyの反転は確信度の高いシグナル |
| liquidation.cluster | 清算リスクスコアが閾値を超える | クラスターゾーンは価格を引き寄せる。特にボラタイルなセッションで顕著 |
| position.large | 想定元本が閾値を超えるポジションが建てられるか閉じられる | WhaleのエントリーとイグジットはHyperliquidの相場を動かす |
| order_flow.spike | 5分間のオーダーフロー出来高がZスコアの閾値を超える | 急激なフローの急増は方向性のある動きに先行することが多い |
これらはHyperTrackerダッシュボードの Settings > Webhooks から設定するか、ウェブフック管理エンドポイントを通じてプログラム的に設定できる。各イベントタイプはオプションのフィルターを受け付ける:アセットシンボル、コホートID、最小想定元本サイズ、閾値。フィルタリングは受信側ではなくソースで行う方が常に優れている。ペイロード量が減り、処理ロジックがクリーンに保たれるからだ。
Telegramへのアラートルーティング
Telegramが暗号資産トレーダーのデフォルト通知チャンネルになっているのは、速く、リッチなフォーマットをサポートし、あらゆるデバイスで動くからだ。ルーティング関数は検証済みのウェブフックペイロードを受け取り、フォーマットされたメッセージをTelegramのチャットやグループに送信する。
async function sendTelegramAlert(event) {
const TELEGRAM_TOKEN = process.env.TELEGRAM_BOT_TOKEN;
const CHAT_ID = process.env.TELEGRAM_CHAT_ID;
const message = formatMessage(event);
await fetch(
`https://api.telegram.org/bot${TELEGRAM_TOKEN}/sendMessage`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
chat_id: CHAT_ID,
text: message,
parse_mode: 'HTML',
}),
}
);
}
function formatMessage(event) {
switch (event.type) {
case 'cohort.shift':
return [
`<b>Cohort Shift: ${event.data.asset}</b>`,
`${event.data.cohort_name} flipped <b>${event.data.direction}</b>`,
`Net position: ${event.data.net_position.toFixed(2)}`,
`Time: ${new Date(event.timestamp).toUTCString()}`,
].join('\n');
case 'liquidation.cluster':
return [
`<b>Liquidation Cluster: ${event.data.asset}</b>`,
`Risk score: ${event.data.risk_score}/100`,
`Price zone: $${event.data.price_low} - $${event.data.price_high}`,
`Estimated exposure: $${(event.data.notional / 1e6).toFixed(1)}M`,
].join('\n');
default:
return `<b>${event.type}</b>\n${JSON.stringify(event.data, null, 2)}`;
}
}
Telegramボットを作成するには、Telegramで@BotFatherにメッセージを送り、/newbotを実行して、トークンを保存する。ボットをアラートチャンネルまたはグループに追加し、getUpdatesエンドポイントからチャットIDを取得する。この一連の作業は2分ほどで完了する。
Discordへの代替ルーティング
チームがDiscordで動いている場合、ウェブフックの配信はさらにシンプルになる。Discordのチャンネルには組み込みのウェブフックURLがある。ボットトークンの管理は不要だ:
async function sendDiscordAlert(event) {
const DISCORD_WEBHOOK_URL = process.env.DISCORD_WEBHOOK_URL;
await fetch(DISCORD_WEBHOOK_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
embeds: [{
title: `${event.type}: ${event.data.asset}`,
description: formatMessage(event),
color: event.data.direction === 'long' ? 0x22c55e : 0xef4444,
timestamp: event.timestamp,
}],
}),
});
}
processEventルーター
受信サーバーと配信チャンネルが整ったら、ルーターがそれらをつなぎ合わせる。どのイベントをどこに送るかを決め、ローカルフィルタリングを適用し、デバッグ用の永続化を追加するのがここだ。
async function processEvent(event) {
// Log every event for debugging and replay
console.log(JSON.stringify({ ts: Date.now(), event }));
// Route by event type and severity
switch (event.type) {
case 'cohort.shift':
// Only alert on the high-conviction cohorts
const alertCohorts = [
'Money Printer', 'Smart Money', 'Leviathan', 'Tidal Whale'
];
if (alertCohorts.includes(event.data.cohort_name)) {
await sendTelegramAlert(event);
await sendDiscordAlert(event);
}
break;
case 'liquidation.cluster':
// Adjust threshold to your risk tolerance
if (event.data.risk_score > 75) {
await sendTelegramAlert(event);
}
break;
case 'position.large':
await sendTelegramAlert(event);
break;
case 'order_flow.spike':
// Example: z > 3 catches extreme spikes. Tune for your strategy.
if (event.data.z_score > 3) {
await sendTelegramAlert(event);
}
break;
default:
console.log('Unhandled event type:', event.type);
}
}
フィルタリング層に注目してほしい。cohort.shiftハンドラーはMoney Printer、Smart Money、Leviathan、Tidal Whaleのみアラートを発火させる。これらは方向転換が最もシグナルとして機能するコホートだ。累積損益$1M以上のウォレット(Money Printer)、$10万〜$100万(Smart Money)、そして最大アカウントサイズ(Tidal Whaleは$100万〜$500万、Leviathanは$500万以上)。 ShrimpやFishコホートのシフトが無意味というわけではないが、信頼性を保つべき通知チャンネルにとってはノイズが多すぎる。
イベントを取りこぼさない障害対応
分散システムは障害を起こす。デプロイ中にサーバーがダウンする。荒れた1時間にTelegramにレートリミットをかけられる。Discordが30秒間502を返す。アラートパイプラインがこうした障害に対応していなければ、最も重要なイベント、つまり混乱の最中に発火するイベントを見逃してしまう。
相性のよい2つのパターンを紹介する:
1. ローカルリトライキュー
配信チャンネルが失敗した場合、イベントを捨てるのではなくリトライキューに積む。低ボリュームの設定ならシンプルなインメモリ配列で十分だ。本番環境ではRedisや永続キューを使う:
const retryQueue = [];
async function safeDeliver(deliverFn, event, channel) {
try {
await deliverFn(event);
} catch (err) {
console.error(`Delivery failed (${channel}):`, err.message);
retryQueue.push({ deliverFn, event, channel, attempts: 1 });
}
}
// Process retries every 30 seconds
setInterval(async () => {
const batch = retryQueue.splice(0, 10);
for (const item of batch) {
try {
await item.deliverFn(item.event);
} catch {
item.attempts++;
if (item.attempts < 5) retryQueue.push(item);
else console.error('Dropped after 5 retries:', item.event.type);
}
}
}, 30_000);
2. 再生用イベントログ
ルーティングの前に、受信したすべてのウェブフックをファイルまたはデータベースに記録する。フォーマットロジックのバグを発見したり、配信チャンネルを見逃したりした場合に、ログを再生してアラートをバックフィルできる。上記のprocessEventのJSONロギング行がこの最もシンプルな実装だ。本番環境ではファイルに追記するか、SQLiteのテーブルに書き込む。
ウェブフックパイプラインのテスト
実際の市場イベントに頼る前に、合成ペイロードでパイプライン全体を端から端まで検証する。現実的なペイロード形式でローカルエンドポイントにテストのPOSTを送る:
curl -X POST http://localhost:3000/webhooks/hypertracker \
-H "Content-Type: application/json" \
-H "x-ht-signature: test-skip-in-dev" \
-d '{
"event_id": "test-001",
"type": "cohort.shift",
"timestamp": "2026-07-10T14:30:00Z",
"data": {
"asset": "ETH",
"cohort_name": "Money Printer",
"cohort_id": 8,
"direction": "short",
"net_position": -1247.5
}
}'
TelegramチャンネルまたはDiscordサーバーがフォーマットされたアラートを受信することを確認する。次に失敗パスをテストする。Telegramのボットトークンを一時的に無効にし、別のテストイベントを送って、リトライキューに入ることを確認する。この2つのチェック、正常系と異常系で、本番稼働前に統合上の問題のほとんどを検出できる。
HyperTrackerダッシュボードのウェブフック設定ページには「テストイベントを送信」ボタンもある。これは本番の配信パイプラインを通じて実際のペイロード形式を発火させるので、市場イベントを待たずにエンドポイントが到達可能で正しく応答しているかを検証できる。
アラートから自動化へ
アラートパイプラインが動き始めたら、自然な次のステップはそれらのシグナルにプログラム的に反応することだ。Telegramにルーティングするのと同じprocessEvent関数が、トレードの実行、ポジションの調整、ダッシュボードの更新もトリガーできる。Money PrinterがBTCでネットショートに転換したコホートシフトで、自動的にストップロスを絞り込む。現在価格より上に清算クラスターが形成されたら、ヘッジをトリガーする。
このアーキテクチャがスケールするのは、ウェブフックが検知とアクションを切り離しているからだ。受信サーバーは「何かが起きた」層を担う。別のモジュールが「それに対して何をするか」層を担う。新しいアクション(Slackへの投稿、データベースへの記録、TradingViewアラートのトリガー)を追加しても、受信サーバーや署名検証に手を触れる必要はない。
HyperTrackerはHyperliquid上のすべてのウォレットを16の行動コホートに分類している。アカウントサイズ別の8つ(ShrimpからLeviathan)と、通算損益別の8つ(Money PrinterからGiga-Rekt)だ。 これらの分類が集計レベルで変化したとき、ウェブフックが発火する。そのシフトが自分のポジションにとって何を意味するかを判断し、対応を組み込むのがあなたの仕事だ。
ウェブフックで構築を始めよう
ウェブフック配信はHyperTrackerのFlow($799/月)とStream($1,999/月)のティアで利用できる。 Flowはウェブフックに加え、月間40万件のAPIリクエストと毎分200リクエストのレートリミットを提供する。Streamはさらにウェブソケット配信、月間200万リクエスト、毎分500リクエストを追加する。どちらも、このガイドで紹介したアラートイベントを動かすコホート分析、オーダーフロー、清算リスクのエンドポイントをすべて含んでいる。
多くのトレーディングインフラがポーリングループから始まるのは、それがチュートリアルで紹介されているパターンだからだ。本番グレードのシステムを構築するビルダーたちは、できる限り早くプッシュ配信に移行する。シグナル検知の1分のレイテンシが積み重なって、逃したトレードと古びたアラートになるからだ。今30分セットアップすれば、相場が動いている夜中の3時に不安定なcronジョブをデバッグする羽目を免れる。