DEV Community

EmilyL
EmilyL

Posted on

Handling Time Boundaries for Hong Kong Stock API Real-Time Data

When our team started working with a Hong Kong stock API for a trading platform, we thought the hard part would be WebSocket reconnection or handling high message rates. It wasn't. The real pain was time boundaries — especially around market open, close, and midnight.

In this post, I'll share the approach we developed for professional trading systems and fund development teams. It's focused on extensibility and clean separation of concerns.

The Problem: Naive Time Checks Break at the Edges

Consider this common pattern:

if current_time >= time(9, 30):
    market_open = True
Enter fullscreen mode Exit fullscreen mode

Looks fine, right? But at 17:00, market_open is still True. You've now labeled after-hours data as live trading data. If your risk engine or strategy consumes this, you have a silent bug.

The issue is that Hong Kong's trading day has multiple phases, not just “open” and “closed.”

Data Model: Define Sessions Explicitly

We start by splitting the day into discrete sessions:

Session Hong Kong Time Programmatic Treatment
Pre-open auction 09:00–09:30 Pre-market data
Morning session 09:30–12:00 Continuous trading
Lunch break 12:00–13:00 Non-trading
Afternoon session 13:00–16:00 Continuous trading
Post-close After 16:00 Non-trading

Then we use interval logic instead of a single threshold:

def is_market_open(t):
    morning = time(9, 30) <= t < time(12, 0)
    afternoon = time(13, 0) <= t < time(16, 0)
    return morning or afternoon
Enter fullscreen mode Exit fullscreen mode

This removes ambiguity at boundaries like 16:00 and 09:30.

Timezone Normalization: Always Convert to Asia/Hong_Kong

A typical Hong Kong stock API returns Unix timestamps:

{
    "symbol": "00700.HK",
    "price": 520.5,
    "timestamp": 1788226200
}
Enter fullscreen mode Exit fullscreen mode

A Unix timestamp is an absolute instant, but it doesn't carry timezone info. If your server is in UTC or Singapore, you must convert:

from datetime import datetime
from zoneinfo import ZoneInfo

timestamp = 1788226200
dt = datetime.fromtimestamp(
    timestamp,
    tz=ZoneInfo("Asia/Hong_Kong")
)
print(dt)
Enter fullscreen mode Exit fullscreen mode

Only after conversion do we run session logic. This prevents server timezone changes from breaking your market state.

Pre-Open Data: A Distinct State

Between 09:00 and 09:30, quotes exist, but they are not continuous trading data. We don't mark it as market_open=True.

We use a state enum:

def get_market_status(t):
    if time(9, 0) <= t < time(9, 30):
        return "pre_open"
    if time(9, 30) <= t < time(12, 0):
        return "morning"
    if time(12, 0) <= t < time(13, 0):
        return "break"
    if time(13, 0) <= t < time(16, 0):
        return "afternoon"
    return "closed"
Enter fullscreen mode Exit fullscreen mode

This allows the UI to show “Pre-open” while strategies consume only morning and afternoon. Clean decoupling.

Cross-Date Issues and Trading Calendar

At 1 AM, this check:

if current_time > time(16, 0):
    status = "closed"
Enter fullscreen mode Exit fullscreen mode

will correctly return closed for session state. But if you also need to know the current trading day, comparing only time is insufficient. You need the date.

Our rule: session state uses datetime.time; trading day uses datetime.date. Never mix them in one variable.

Also, Hong Kong has public holidays. Don't assume weekdays are trading days. Maintain a separate trading calendar.

K-Line Aggregation: Strict Boundaries

When you build 1-minute candles from tick data, boundaries must be precise. 09:29:59 and 09:30:00 are different minutes.

We use left-closed, right-open intervals:

09:30:00 <= tick_time < 09:31:00

This ensures each tick falls into exactly one candle.

In practice, when integrating with ALLTICK API, we convert all timestamps to Asia/Hong_Kong before session checks and K-line aggregation, following the API's documented field structure.

Our Processing Pipeline

Here's the flow we use:

API real-time data
     ↓
Parse timestamp
     ↓
Convert to Asia/Hong_Kong
     ↓
Determine trading date
     ↓
Determine session state
     ↓
Filter/classify quotes
     ↓
K-line aggregation or strategy calculation
Enter fullscreen mode Exit fullscreen mode

By isolating time logic and avoiding magic numbers like 09:30 or 16:00, we made the system easier to extend to other markets.

Key Takeaways

  • Separate data time from trading time.
  • Always convert timestamps to Asia/Hong_Kong before session logic.
  • Use interval checks, not point comparisons.
  • Treat pre-open and post-close as distinct states.
  • Keep session state and trading day in separate variables.

Time boundaries are foundational. Get them right, and everything downstream becomes simpler.

What time-related bugs have you encountered in market data systems? Let me know in the comments!

Top comments (0)