AllTick
-
リアルタイム市場データ株式 api金融データ api

リアルタイム米国株APIで株式ウォッチリストを構築する方法

WebSocketを使ってリアルタイムの米国株ウォッチリストを構築する方法を解説します。複数銘柄の購読、ハートビート、再接続、価格更新、購読容量を扱います。

AllTick読了 5 分

株式ウォッチリストは、画面上ではシンプルに見えます。銘柄コード、最新株価、そして値上がり率や値下がり率を一覧表示するだけです。しかし、複数の銘柄をページの再読み込みなしで継続的に更新しようとすると、実装上の課題が生じます。

リアルタイム株価トラッカーや株式監視ダッシュボードを開発するフィンテック開発者にとって、HTTPエンドポイントに繰り返しリクエストを送って価格を取得する方法は、必ずしも最適とは限りません。ウォッチリストの銘柄数が増えるにつれて、頻繁なポーリングは不要なリクエストを増やし、更新の一貫性を維持することも難しくなります。

より実用的な方法は、サーバー側で1つのWebSocket接続を維持し、選択した米国株を購読して、新しい取引データが届くたびに対応するウォッチリスト項目を更新することです。以下では、AllTickのリアルタイム米国株APIを使用した実装方法を紹介します。

継続的なデータストリームを中心にウォッチリストを設計する

使いやすいウォッチリストを構築するには、価格を受信する接続だけでは不十分です。受信した各更新を正しい銘柄に関連付け、そのデータをダッシュボードで利用できるようにする仕組みが必要です。

実用的なアーキテクチャは、次の3つの要素で構成されます。

  • マーケットデータ接続: バックエンドサービスが株式WebSocketエンドポイントに接続し、選択した銘柄を購読します。
  • 価格データ処理: バックエンドが取引データを受信し、銘柄ごとの最新価格を管理します。
  • ダッシュボードインターフェース: フロントエンドがバックエンドから最新データを取得し、対応する行を更新します。

マーケットデータ接続をバックエンド側に置くことで、APIトークンの漏えいも防止できます。ブラウザのJavaScriptにトークンを直接記述すると、訪問者がその内容を確認し、再利用できてしまいます。

少数の銘柄を監視する場合は、インメモリのMapで最新価格を保持できます。複数のバックエンドインスタンス間で同じ価格データを共有する必要がある大規模なアプリケーションでは、Redisなどの共有キャッシュを利用できます。

WebSocketで複数の米国株を購読する

AllTickは、株式と指数向けの専用WebSocketエンドポイントを提供しています。米国株の銘柄コードには、NVDA.US、MSFT.US、AMD.US のような取引所を識別するサフィックスが含まれます。

最新約定価格の購読にはプロトコル 22004 を使用します。購読が正常に受け付けられると、22005 の応答が返され、その後、22998 のプロトコルを通じて取引データがプッシュ配信されます。各更新には銘柄コードが含まれるため、アプリケーション側でどのウォッチリスト項目を更新すべきか識別できます。

Node.jsのWebSocketパッケージをインストールします。

text
npm install ws

APIトークンをアプリケーションに直接記述せず、サーバー側の環境変数に保存します。

text
ALLTICK_API_TOKEN=your_api_token

次のコード例では、WebSocket接続の確立、複数銘柄の購読、ハートビートの送信、受信した価格データの保存を行います。

text
const WebSocket = require("ws");
const { randomUUID } = require("crypto");

const token = process.env.ALLTICK_API_TOKEN;

if (!token) {
  throw new Error("Missing AllTick API token");
}

const symbols = [
  "NVDA.US",
  "MSFT.US",
  "AMD.US"
];

let ws;
let heartbeat;
let sequence = 0;

const latestQuotes = new Map();

function sendMessage(cmd_id, data = {}) {
  if (ws?.readyState !== WebSocket.OPEN) return;

  ws.send(JSON.stringify({
    cmd_id,
    seq_id: ++sequence,
    trace: randomUUID(),
    data
  }));
}

function subscribeStocks() {
  sendMessage(22004, {
    symbol_list: symbols.map(code => ({ code }))
  });
}

function connect() {
  ws = new WebSocket(
    `wss://quote.alltick.co/quote-stock-b-ws-api?token=${encodeURIComponent(token)}`
  );

  ws.on("open", () => {
    console.log("Stock WebSocket connected");

    subscribeStocks();

    heartbeat = setInterval(() => {
      sendMessage(22000);
    }, 10_000);
  });

  ws.on("message", raw => {
    let packet;

    try {
      packet = JSON.parse(raw.toString());
    } catch (error) {
      console.error("Invalid message:", error);
      return;
    }

    if (packet.cmd_id === 22005 && packet.ret !== 200) {
      console.error("Subscription failed:", packet.msg);
      return;
    }

    if (packet.cmd_id !== 22998 || !packet.data) {
      return;
    }

    const { code, price, volume, tick_time } = packet.data;

    latestQuotes.set(code, {
      price,
      lastTradeSize: volume,
      tickTime: Number(tick_time)
    });

    console.log("Updated watchlist:", code, latestQuotes.get(code));
  });

  ws.on("close", () => {
    clearInterval(heartbeat);
    console.log("Connection closed. Reconnecting...");

    setTimeout(connect, 10_000);
  });

  ws.on("error", error => {
    console.error("WebSocket error:", error);
  });
}

connect();

このコード例は、マーケットデータを受信するための基本レイヤーを実装しています。アプリケーション側では、latestQuotes の更新内容を独自のWebSocketやServer-Sent Events(SSE)を通じてフロントエンドに配信できます。

重要なのは、WebSocket接続を継続的に維持することです。AllTickでは10秒ごとのハートビート送信が必要で、30秒以内にハートビートリクエストが届かない場合、接続は切断されます。このコード例では、接続が閉じられた後に再接続し、最初の購読リストを再送信します。

ウォッチリスト全体を再構築せずに対象銘柄を更新する

リアルタイム株式ウォッチリストでは、受信したデータに対応する銘柄の行だけを更新することが重要です。

例えば、NVDA.US のメッセージを受信した場合、MicrosoftやAMDの保存済み価格を置き換えることなく、NVIDIAの価格だけを更新します。

そのため、code フィールドが重要になります。このフィールドは、マーケットデータの更新とウォッチリスト内の該当項目を結び付けるキーとして機能します。

また、最新取引の出来高と、その日の累計出来高を区別する必要があります。取引プッシュに含まれる volume フィールドは、直近の取引に関連する出来高を表します。そのまま1日の累計出来高として表示してはいけません。

価格変動率を表示するダッシュボードでは、前日終値も必要です。次の計算式で変動率を算出できます。

-
-

市場価格を保存する際は、元の小数値を維持してください。金融計算では、通常のJavaScriptの浮動小数点演算に依存するのではなく、Decimal演算ライブラリを使用することを推奨します。

もう1つの有効な対策は、最後にデータを受信した時刻を記録することです。これにより、ダッシュボード上に表示されている価格が最新のものなのか、接続が中断した後に残っている古い値なのかを区別できます。

ウォッチリスト拡張前に購読可能な銘柄数を確認する

5銘柄を監視するウォッチリストと、数百銘柄を追跡する監視ダッシュボードでは、必要となるデータ容量が異なります。

AllTickの購読可能な銘柄数はプランによって異なります。現在の料金情報では、Basicは選択可能な銘柄が100、Premiumは200、Professionalは3,000となっています。All US Stocksプランは約11,000銘柄の米国株をカバーしていますが、1つの接続で同時に購読できる銘柄数は3,000までです。

ユーザーがウォッチリストに銘柄を追加・削除する際には、もう1つ重要な購読仕様があります。新しい購読リクエストを送信すると、デフォルトでは以前の購読リストが置き換えられます。そのため、バックエンド側でウォッチリスト全体を管理し、内容が変更されるたびに更新後の完全なリストを再送信する必要があります。新しく追加した銘柄だけを送信すると、既存の購読が置き換えられてしまう可能性があります。

最新価格だけが必要なアプリケーションであれば、より軽量なクォート取得方式で十分な場合もあります。一方、継続的にプッシュされる取引データが必要なダッシュボードでは、リアルタイムTickデータに対応したプランを選択してください。Freeプランには最新価格と終値データが含まれており、リアルタイムTickデータは有料プランの機能として提供されています。

AllTickは、RESTとWebSocketの両方を通じて株式マーケットデータを提供しています。そのため、銘柄の基本情報と継続的な価格データストリームを組み合わせることができます。リアルタイム株式ウォッチリストを開発する場合は、必要な購読数に応じてAllTick WebSocket APIドキュメントと利用可能なAPIプランを確認してください。

信頼性の高いリアルタイム株価トラッカーは、単に価格が変化する表を表示するだけではありません。正確な銘柄コードの対応付け、継続的な購読、ハートビート処理、適切な価格データ管理が必要です。これらの仕組みを正しく実装することで、ウォッチリストの規模が拡大しても安定して運用できるダッシュボードの基盤を構築できます。

今すぐマーケットデータ配信を開始

数秒で無料 API キーを発行し、1 つのエンドポイントからすべての市場に接続できます。