DEV Community

kalos
kalos

Posted 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)

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

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)