AllTick
-
stock api real-time market datafinancial data api

How to Build a Real-Time Stock Watchlist with a Real-time US Stock API

Build a real-time US stock watchlist with WebSocket, covering multi-symbol subscriptions, heartbeat handling, reconnection, quote updates, and subscription capacity planning.

AllTick5 min read

A stock watchlist looks simple on the screen: a list of tickers, their latest prices, and perhaps a percentage change. The real challenge starts when several stocks need to update continuously without refreshing the page.

For fintech developers building a live stock tracker or stock monitoring dashboard, repeatedly requesting prices from an HTTP endpoint is not always the most practical approach. As the watchlist grows, frequent polling creates unnecessary requests and makes it harder to keep updates consistent.

A better approach is to maintain one server-side WebSocket connection, subscribe to the selected US stocks, and update each watchlist item whenever a new trade arrives. This is the approach used in the following example with the AllTick Real-time US Stock API.
Design the Watchlist Around a Persistent Data Stream
A useful watchlist needs more than a connection that receives prices. It needs a way to associate every incoming update with the correct stock and make that update available to the dashboard.

A practical architecture has three parts:

  • Market data connection: A backend service connects to the stock WebSocket endpoint and subscribes to selected symbols.
  • Quote processing: The backend receives trade updates and maintains the latest quote for each symbol.
  • Dashboard interface: The frontend reads the latest values from the backend and updates the corresponding rows.
    Keeping the market data connection on the backend also protects the API token. Exposing the token in browser JavaScript would allow visitors to inspect and reuse it.

For a small watchlist, an in-memory map can hold the latest prices. A larger application can use Redis or another shared cache when several backend instances need access to the same quote data.
Subscribe to Multiple US Stocks Through WebSocket
AllTick provides a dedicated WebSocket endpoint for stocks and indices. US stock symbols use exchange-qualified codes, such as NVDA.US, MSFT.US, and AMD.US.

The latest trade price subscription uses protocol 22004. After a successful subscription response (22005), the server pushes trade updates through protocol 22998. Each update includes a stock code, allowing the application to identify which watchlist item needs refreshing.

Install the Node.js WebSocket package:

text
npm install ws

Store the AllTick API token in a server-side environment variable rather than hardcoding it in the application:

text
ALLTICK_API_TOKEN=your_api_token

The following example establishes the connection, subscribes to several stocks, sends heartbeats, and stores incoming prices.

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();

This example provides the market-data ingestion layer. The application can publish changes from latestQuotes to its frontend through its own WebSocket or server-sent events connection.

One important detail is that the connection must remain active. AllTick requires a heartbeat every 10 seconds, and a connection will be disconnected if no heartbeat request is received within 30 seconds. The example also reconnects after a closed connection and resends the original subscription list.

Update the Correct Stock Without Rebuilding the Watchlist

A real-time stock watchlist should update only the row associated with the incoming symbol.

For example, when a message for NVDA.US arrives, the backend should update NVIDIA's quote without replacing the values stored for Microsoft or AMD.

The code field is therefore essential. It acts as the key that connects a market-data update to the relevant watchlist entry.

It is also important to distinguish between the latest trade volume and the day's cumulative trading volume. The volume field in the trade push represents the volume associated with the latest transaction. It should not automatically be displayed as total daily volume.

For a dashboard that displays price changes, the backend also needs a previous-close reference. The percentage change can then be calculated as:

-
-

Keep the original decimal values when storing market prices. For financial calculations, use a decimal arithmetic library rather than relying on ordinary JavaScript floating-point operations.

Another useful safeguard is to track the timestamp of the last received update. This allows the dashboard to distinguish a recently updated quote from an old value that remains visible after a connection interruption.

Plan Subscription Capacity Before Expanding the Watchlist

A watchlist with five stocks and a monitoring dashboard tracking hundreds of symbols have different data requirements.

AllTick's subscription limits depend on the plan. The current pricing information lists 100 selected products for Basic, 200 for Premium, and 3,000 for Professional. The All US Stocks plan covers approximately 11,000 US stock symbols, but its documented simultaneous subscription limit is 3,000 products per connection.

There is also an important subscription behavior to consider when users add or remove stocks dynamically: a new subscription request replaces the previous subscription list by default. The backend should therefore maintain the complete watchlist and resend the updated list whenever its contents change. Sending only the newly added stock may cause existing subscriptions to be replaced.

For applications that only need latest prices, a lighter quote-based approach may be sufficient. When the dashboard needs continuously pushed trade updates, choose a plan that includes real-time tick access. The Free plan lists latest price and close data, while real-time tick is listed among the features of paid plans.

AllTick provides stock market data through REST and WebSocket interfaces, making it possible to combine reference data with a continuous quote stream. Developers building a real-time stock watchlist can review the AllTick WebSocket API documentation and available API plans before selecting the subscription capacity needed by their application.

A reliable live stock tracker is not just a table that displays changing prices. It depends on correct symbol mapping, persistent subscriptions, heartbeat handling, and sensible quote-state management. Getting these parts right gives the dashboard a stable foundation as the watchlist grows.

Start streaming market data today

Generate a free API key in seconds and connect to every market from one endpoint.