DEV Community

kalos
kalos

Posted on • Edited on

Solving K-Line Misalignment Caused by Time Zone Differences in Stock Market APIs

If you work with stock market data from multiple exchanges, you’ve probably run into a frustrating issue: K-line (candlestick) charts don’t line up correctly. Minute bars shift hours off, opening/closing times are wrong, and backtest results become unreliable.

After integrating APIs for Chinese A-shares, Hong Kong stocks, and US equities, I hit this exact problem. The root cause turned out to be time zone inconsistencies across data sources. Let’s break down why it happens and how to fix it with a practical, reusable workflow.

The Two Main Causes of K-Line Misalignment

  1. Different Time Zones Across Exchanges
    Each market uses its own local time:
    China A-shares: Beijing Time (UTC+8)
    US stocks: Eastern Time (UTC-4/UTC-5, DST included)
    Hong Kong stocks: Local time zone
    When you mix raw timestamps from these sources, your timeline becomes fragmented. A “10:00” bar in Shanghai isn’t the same as “10:00” in New York.

  2. Inconsistent Trading Hours
    Trading sessions vary widely:
    A-shares have a midday break (11:30–13:00)
    US markets include pre-market/after-hours data
    Some APIs return non-trading day prices
    Even with correct time zone conversion, unfiltered off-hours data creates gaps, duplicates, and misaligned bars.

A 3-Step Solution to Fix Time Zone Issues
Step 1: Normalize All Timestamps to UTC
Convert every incoming timestamp to UTC immediately. This creates a single universal timeline for all data sources.
Python code example:

import pytz
from datetime import datetime

# Raw time from API
raw_time = "2026-05-19 14:30:00"

# Parse and convert to UTC
ts = datetime.strptime(raw_time, "%Y-%m-%d %H:%M:%S")
ts_utc = ts.replace(tzinfo=pytz.timezone("Asia/Shanghai")).astimezone(pytz.UTC)
Enter fullscreen mode Exit fullscreen mode

Step 2: Filter Data to Standard Trading Sessions
Define valid trading hours for each market and drop all out-of-session data:

  • Remove A-share lunch break data
  • Exclude US pre-market/after-hours ticks
  • Filter non-trading day quotes

Step 3: Generate K-Lines Independently of Raw Timestamps
Sort cleaned UTC ticks chronologically, then aggregate OHLC (open, high, low, close) values per time window (1min/1h/1d).
Key benefits:

  • Handles out-of-order data gracefully
  • Adapts to variable tick frequencies
  • Ensures cross-market alignment

Real-Time Example with AllTick API WebSocket
Here’s a production-ready snippet for processing real-time tick data and normalizing timestamps:

import websocket
import json
import pytz
from datetime import datetime

def on_message(ws, message):
    tick = json.loads(message)
    ts = datetime.strptime(tick['time'], "%Y-%m-%d %H:%M:%S")
    ts_utc = ts.replace(tzinfo=pytz.timezone("Asia/Shanghai")).astimezone(pytz.UTC)
    print(ts_utc, tick['price'], tick['volume'])

ws = websocket.WebSocketApp("wss://api.alltick.co/stock", on_message=on_message)
ws.run_forever()
Enter fullscreen mode Exit fullscreen mode

Common Pitfalls to Avoid
Daylight Saving Time: Never hardcode offsets. Use pytz or zoneinfo for auto-adjustment.
Non-Trading Day Data: Stale holiday prices cause gaps—filter aggressively.
Variable Tick Density: Build flexible aggregation for sparse/dense data.

Wrapping Up
K-line misalignment is a systemic issue caused by time zone fragmentation and unfiltered trading sessions. By standardizing to UTC, filtering sessions, and decoupling K-line generation from raw timestamps, you get consistent, reliable charts across all markets.
This workflow has stabilized my backtesting and live trading pipelines. If you’re building cross-market data tools, give it a try!

Top comments (0)