AllTick
-
Hong Kong Stocks stock api Market DataFintech Development

How to Handle Data Gaps During the Midday Break When Connecting to a Hong Kong Stock API for Real-Time Quotes?

Learn how to handle the Hong Kong stock market lunch break in real-time API systems. Separate trading sessions, WebSocket health, and tick updates to avoid false alerts and ensure smooth data recovery after trading resumes.

AllTick5 min read

When developing a Hong Kong stock market monitoring system, the midday break is an easy situation to mistake for an API failure.

For example, a page is subscribed to the real-time quotes for Tencent Holdings (700.HK). New trade data is still received at 11:59 AM, but price updates suddenly stop after 12:00 PM. The WebSocket connection remains open and the heartbeat is working normally, but the server no longer pushes new Tick data.

If the system relies only on quote update timestamps to determine whether the connection is healthy, it may repeatedly attempt to reconnect during the lunch break. When afternoon trading resumes, problems with resubscription, data caching, or frontend state management may also delay the return of quote updates.

Handling this situation requires more than checking whether the API continues to push data. Developers need to evaluate trading sessions, WebSocket connection status, and individual securities' quote updates separately.

Does the Hong Kong Stock Market Always Stop Trading After 12:00 PM?

Before developing a real-time Hong Kong stock market application, there is one detail to understand: not all Hong Kong-listed securities follow exactly the same midday trading arrangements.

Under the Hong Kong Exchange's securities market trading rules, the continuous trading sessions for ordinary securities run from 9:30 AM to 12:00 PM and from 1:00 PM to 4:00 PM. This means ordinary securities have no continuous trading between 12:00 PM and 1:00 PM.

However, certain securities designated as Extended Trading Securities can continue trading during the Extended Morning Session from 12:00 PM to 1:00 PM. Half-day trading sessions also follow different arrangements and should not be handled using the same schedule as a regular full trading day.

During development, you can first classify trading sessions according to the following rules:

Security and Trading Day TypeMorning12:00–13:00Afternoon
Ordinary securities on a full trading day09:30–12:00Lunch break13:00–16:00
Designated Extended Trading Securities on a full trading day09:30–12:00Extended Morning Session13:00–16:00
Half trading day09:30–12:00Continuous trading has endedNo afternoon session

All times in the table are Hong Kong time. Arrangements such as the closing auction session on half trading days need to be handled separately.

Therefore, a system monitoring multiple Hong Kong stocks should not automatically mark every security as suspended at 12:00 PM. It should first check the trading calendar and the trading sessions applicable to each security. Only then should it determine which securities have entered the lunch break and whether quote anomaly detection is necessary.

Separate Market Status from WebSocket Connection Status

One of the most common development mistakes is treating "no Tick received" as equivalent to "the market data API is not working."

These are two different situations.

A market data system should manage three independent states: market trading status, WebSocket connection status, and quote update status for each security.

Detection ScenarioWhat HappensRecommended Handling
Normal lunch breakThe trading calendar indicates a break, the heartbeat is normal, and no new Tick is receivedKeep the last valid price and do not reconnect
Temporary lack of trades during trading hoursThe connection is healthy, but a particular security has no new TickPreserve the original timestamp and check trading activity
Subscription failureA subscription response is received, but it contains an error codeCheck the security symbol, Token, and account permissions
Connection failureThe WebSocket disconnects or receives no heartbeat response for an extended periodRe-establish the connection and restore subscriptions

The distinction between heartbeats and market data pushes is particularly important.

A heartbeat is used to confirm that the communication channel is still functioning. A Tick represents an update to actual trade data. Even when the connection is healthy, not every stock will continuously generate new trades.

For example, suppose the last trade in the morning occurred at 11:59:58 AM. If the page still displays that price at 12:30 PM, this is reasonable. The system should preserve the original trade timestamp and display the status as a lunch break. It should not change the price timestamp to 12:30 PM.

Use Hong Kong Time and the Security Trading Calendar to Identify Market Breaks

To prevent the lunch break from being mistaken for a connection failure, trading session detection can be implemented on the market data server as a separate state management layer before WebSocket messages are processed.

The following JavaScript example identifies the continuous trading sessions for ordinary securities and designated Extended Trading Securities.

text
function getHKMinutes(now = new Date()) {
  const parts = new Intl.DateTimeFormat("en-GB", {
    timeZone: "Asia/Hong_Kong",
    hour: "2-digit",
    minute: "2-digit",
    hourCycle: "h23"
  }).formatToParts(now);

  const hour = Number(
    parts.find(p => p.type === "hour").value
  );
  const minute = Number(
    parts.find(p => p.type === "minute").value
  );

  return hour * 60 + minute;
}

function getHKSession({
  now = new Date(),
  isTradingDay,
  isHalfDay = false,
  isExtendedTradingSecurity = false
}) {
  if (!isTradingDay) return "MARKET_CLOSED";

  const time = getHKMinutes(now);

  if (time >= 570 && time < 720) {
    return "MORNING_SESSION";
  }

  if (isHalfDay && time >= 720) {
    return "HALF_DAY_AFTER_CONTINUOUS_SESSION";
  }

  if (
    time >= 720 &&
    time < 780 &&
    isExtendedTradingSecurity
  ) {
    return "EXTENDED_MORNING_SESSION";
  }

  if (time >= 720 && time < 780) {
    return "LUNCH_BREAK";
  }

  if (time >= 780 && time < 960) {
    return "AFTERNOON_SESSION";
  }

  return "OUTSIDE_CONTINUOUS_SESSION";
}

There are two points to keep in mind.

First, the values of isTradingDay, isHalfDay, and isExtendedTradingSecurity should come from the trading calendar and the rules applicable to each security. They should not be determined simply by checking whether the day falls between Monday and Friday. Hong Kong public holidays, half trading days, and special trading arrangements can all affect actual trading hours.

Second, this code checks continuous trading sessions only. It does not include the pre-opening session or closing auction session. In a production environment, these states should be added based on a complete trading calendar. This example should not be treated as a complete Hong Kong Exchange trading calendar.

How Should AllTick WebSocket Be Handled During the Lunch Break?

For applications that need continuous quote updates, WebSocket is more suitable for receiving tick-by-tick trade data than repeatedly polling a REST API.

When connecting to Hong Kong stock quotes through AllTick, use the dedicated stock WebSocket endpoint. For example, with 700.HK, the latest trade subscription uses 22004, the successful response is 22005, and subsequent trade data is pushed through 22998.

After establishing the connection, send the following subscription message:

text
{
  "cmd_id": 22004,
  "seq_id": 1,
  "trace": "hk-trade-sub",
  "data": {
    "symbol_list": [
      { "code": "700.HK" },
      { "code": "1288.HK" }
    ]
  }
}

During the lunch break, the normal approach is to keep the WebSocket connection open rather than close it simply because no new trades are being received.

AllTick uses 22000 for its application-level heartbeat request and 22001 for the server response. The official connection instructions require a heartbeat every 10 seconds. The connection will be disconnected if no heartbeat request is received for more than 30 seconds.

In Node.js, the ws library can be used to implement quote reception, heartbeat monitoring, and reconnection after a disconnection.

First, install the dependency:

text
npm install ws

Set the ALLTICK_API_TOKEN environment variable on the server, then use the following example:

text
const WebSocket = require("ws");

const token = process.env.ALLTICK_API_TOKEN;

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

const symbols = ["700.HK", "1288.HK"];

let ws;
let heartbeatTimer;
let reconnectTimer;
let retryMs = 1000;
let sequence = 0;
let lastHeartbeatAck = 0;

const HEARTBEAT_INTERVAL_MS = 10000;

// Client-defined threshold for monitoring heartbeat responses
const HEARTBEAT_ACK_TIMEOUT_MS = 30000;

function send(cmdId, data = {}) {
  if (!ws || ws.readyState !== WebSocket.OPEN) {
    return;
  }

  const seqId = ++sequence;

  ws.send(JSON.stringify({
    cmd_id: cmdId,
    seq_id: seqId,
    trace: `hk-${cmdId}-${seqId}`,
    data
  }));
}

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

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

    retryMs = 1000;
    lastHeartbeatAck = Date.now();

    // Send the complete subscription list after every reconnection
    send(22004, {
      symbol_list: symbols.map(code => ({ code }))
    });

    clearInterval(heartbeatTimer);

    heartbeatTimer = setInterval(() => {
      if (
        Date.now() - lastHeartbeatAck >
        HEARTBEAT_ACK_TIMEOUT_MS
      ) {
        console.error("Heartbeat acknowledgement timeout");
        ws.terminate();
        return;
      }

      send(22000);
    }, HEARTBEAT_INTERVAL_MS);
  });

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

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

    // Subscription result
    if (message.cmd_id === 22005) {
      if (message.ret !== 200) {
        console.error(
          "Subscription failed:",
          message.ret,
          message.msg
        );
      } else {
        console.log("Subscription accepted");
      }
    }

    // Heartbeat response
    else if (message.cmd_id === 22001) {
      lastHeartbeatAck = Date.now();
    }

    // Latest trade push
    else if (message.cmd_id === 22998) {
      onTick(message.data);
    }
  });

  ws.on("close", () => {
    scheduleReconnect();
  });

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

function scheduleReconnect() {
  clearInterval(heartbeatTimer);

  if (reconnectTimer) return;

  const delay = retryMs + Math.floor(Math.random() * 500);

  reconnectTimer = setTimeout(() => {
    reconnectTimer = null;
    connect();
  }, delay);

  retryMs = Math.min(retryMs * 2, 30000);
}

function onTick(tick) {
  // Preserve the original trade event timestamp and record local receipt time separately
  console.log({
    ...tick,
    received_at: Date.now()
  });
}

connect();

This example covers quote subscription, heartbeat requests, heartbeat response handling, trade data reception, and exponential backoff reconnection after a disconnection. The 30-second heartbeat response timeout in the example is a monitoring threshold chosen by the client. It is not an SLA commitment from AllTick regarding response latency.

Two additional points should be considered in a production environment.

First, check the response returned by 22005. When a subscription failure response is received, check the security symbol, Token, and account permissions before taking further action. Reconnecting repeatedly without identifying the cause will not solve a subscription problem.

Second, be aware of the subscription list replacement rule. A new subscription request in AllTick replaces the previous subscription list. Therefore, after reconnecting, the client must submit the complete symbols list again. Otherwise, some previously subscribed stocks may stop receiving quote updates.

How to Confirm That Quotes Have Resumed After Afternoon Trading Begins

The start of trading at 1:00 PM does not mean that every stock will immediately generate a new trade.

The system should use the trading calendar to change the status of ordinary securities from LUNCH_BREAK to AFTERNOON_SESSION. However, whether quotes have actually resumed must still be determined by the data received.

The following sequence is recommended:

  1. Check whether the WebSocket is still connected or has successfully reconnected after a disconnection.
  2. Confirm that the subscription response 22005 indicates success.
  3. When 22998 is received, update the relevant security's price, trade timestamp, and cache.
  4. If the heartbeat is normal but no Tick has arrived, check whether the security has had a new trade and cross-check the result with a REST quote request.

There is another detail that is easy to overlook: market data timestamps and system receipt timestamps are not the same.

For example, a Tick received at 1:02 PM may have a trade timestamp of 1:01:58 PM. The system should preserve the original tick_time provided by the API and separately record the local time when the message was received. The difference between these two timestamps can help developers identify delays in data transmission or processing.

For applications that display minute K-lines, do not generate a synthetic trade simply because no Tick has been received through WebSocket. AllTick WebSocket does not support K-line pushes, so K-line data needs to be retrieved through the HTTP REST API. When aggregating minute K-lines from Tick data, the process should follow actual trading sessions and trade records. A time period with no actual trades should not be represented as though a new trade had occurred.

Handle the Midday Break Correctly in a Hong Kong Stock Market Data System

The data gap during the midday break when connecting to a Hong Kong stock API is essentially a coordination issue between trading calendar management and real-time market data connection management.

The trading calendar determines whether a security is currently within its trading session. The WebSocket heartbeat confirms the communication status, while the Tick timestamp reflects actual trade updates. Managing these three elements separately helps prevent a normal lunch break from being mistaken for an API failure. It also allows the system to identify genuine data issues more quickly after afternoon trading resumes.

AllTick provides APIs for accessing real-time trade data and order book data for Hong Kong stocks. Developers can receive the latest Tick data through the stock WebSocket and combine it with the REST API to retrieve the latest quotes and historical K-lines. For market data services monitoring multiple Hong Kong stocks, subscription lists, trading sessions, and quote caches can also be managed centrally on the server.

When developing a real-time Hong Kong stock monitoring system, visit the AllTick official product page to learn about stock market data API integration. You can then use actual security symbols to verify subscription permissions, trading sessions, and the quote update process.

Start streaming market data today

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