The Problem with Managing Five Different Market Feeds
Picture this: it is 9:28 AM ET on a Tuesday. You are running a cross-asset momentum strategy that requires real-time data from US equities, Hong Kong-listed tech stocks, and Binance futures. Historically, this meant maintaining three separate WebSocket connections, parsing three different protocol formats, handling three distinct authentication mechanisms, and reconciling timestamps from three separate time sources. When one feed hiccupped, you spent 40 minutes debugging before realizing the issue was a timezone mismatch between your HK equity feed and your US equity feed.
This is the exact problem TickDB's unified market data gateway solves. One connection. One protocol. Every market.
In this article, we dissect the technical architecture that makes this possible: how protocol adapters normalize disparate exchange APIs, how the unified data model ensures consistent schema across asset classes, and how timezone standardization eliminates the reconciliation nightmares that plague multi-market trading systems.
The Fragmentation Problem in Real-Time Market Data
Three Markets, Three Different Realities
Before diving into the solution, we must understand the scale of the problem. The three major markets TickDB aggregates—US equities, Hong Kong equities, and cryptocurrency—operate on fundamentally different technical primitives.
| Market | Primary Protocol | Authentication | Timestamp Format | Message Frequency |
|---|---|---|---|---|
| US Equities (SIP) | ITCH over TCP | Binary challenge-response | Nanoseconds since midnight | ~50,000 msg/sec peak |
| HK Equities (HKEX) | OMD-C Binary | HMAC-SHA256 header | Milliseconds UTC | ~20,000 msg/sec peak |
| Crypto (Binance) | WebSocket JSON | API key query param | Milliseconds UTC | Variable, bursty |
Each protocol carries identical semantic concepts—price, quantity, side, timestamp—but wrapped in incompatible wire formats. A US equity order book update arrives as a 4-byte little-endian delta. A Binance depth update arrives as a JSON payload with nested arrays. An HKEX trade arrives as a fixed-offset binary record.
The Operational Cost of Fragmentation
Maintaining separate integrations carries measurable costs beyond mere engineering time. Consider the operational surface area:
- Connection management: Three separate WebSocket clients, each with its own heartbeat logic, reconnection strategy, and error handling.
- Authentication drift: One exchange rotates API keys quarterly; another requires certificate pinning; a third uses a proprietary signature scheme.
- Timestamp chaos: A trade reported at
09:30:00.000on the SIP feed means something different than09:30:00.000on the Binance feed during daylight saving transitions. - Schema proliferation: Your internal order book model must handle three different representations of the same logical structure.
The compounding effect is not linear. Every new market added multiplies the integration complexity.
TickDB's Unified Gateway Architecture
High-Level Design
TickDB's unified gateway is a protocol-agnostic streaming layer that sits between the raw exchange feeds and your application. The architecture consists of three logical layers:
┌─────────────────────────────────────────────────────────────┐
│ Your Application │
│ (Single WebSocket subscription model) │
└────────────────────────┬────────────────────────────────────┘
│ WebSocket (JSON)
▼
┌─────────────────────────────────────────────────────────────┐
│ Unified Gateway Layer │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ US Equity │ │ HK Equity │ │ Crypto │ │
│ │ Protocol │ │ Protocol │ │ Protocol │ │
│ │ Adapter │ │ Adapter │ │ Adapter │ │
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Unified Data Model (UDM) │ │
│ │ Normalized: price, quantity, side, timestamp, │ │
│ │ market, symbol, sequence │ │
│ └─────────────────────────────────────────────────────┘ │
└────────────────────────┬────────────────────────────────────┘
│ Internal pipeline
▼
┌─────────────────────────────────────────────────────────────┐
│ Exchange Connectivity Layer │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ SIP Feed │ │ HKEX OMD-C │ │ Binance WS │ │
│ │ Handler │ │ Handler │ │ Handler │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────┘
This layered approach means your application speaks only to the unified gateway. The complexity of the underlying exchange protocols is abstracted away entirely.
The Protocol Adapter Pattern
Each protocol adapter is responsible for three tasks:
- Decoding: Convert the exchange-specific wire format into the adapter's internal intermediate representation.
- Normalizing: Map the intermediate representation to the Unified Data Model (UDM).
- Translating: Handle market-specific business logic (lot sizes, price tick rules, trading sessions) that affects data interpretation.
The adapter pattern is critical because it isolates market-specific logic. When Binance updates their depth message format, only the crypto adapter changes. The unified gateway and your application code remain unaffected.
The Unified Data Model
Schema Design Principles
The Unified Data Model (UDM) is the lingua franca of TickDB's gateway. Every message, regardless of source, conforms to a consistent schema designed around three principles:
Semantic consistency: Field names represent the same concept everywhere. price always means the fill price. quantity always means the fill quantity. No last_px versus trade_price ambiguity.
Completeness: Every field required for downstream processing is present. Optional fields use explicit null rather than omitting the key.
Lossless extension: Original exchange metadata is preserved in an optional raw envelope for debugging and compliance purposes.
Core Message Types
TickDB's UDM defines four primary message types:
// Trade message (normalized across all markets)
{
"type": "trade",
"market": "US", // Normalized: US | HK | CRYPTO
"symbol": "AAPL.US",
"timestamp": 1709121000000, // Unix milliseconds (UTC)
"price": 182.45,
"quantity": 100,
"side": "buy", // Normalized: buy | sell
"trade_id": "AAPL.US-1709121000000-4521",
"raw": { ... } // Original exchange message (optional)
}
// Order book update (L1-L10 depending on market)
{
"type": "depth",
"market": "HK",
"symbol": "0700.HK",
"timestamp": 1709121000500,
"bids": [[182.40, 5000], [182.38, 12000]],
"asks": [[182.46, 8000], [182.50, 15000]],
"level": 2,
"raw": { ... }
}
// Kline / Candlestick
{
"type": "kline",
"market": "CRYPTO",
"symbol": "BTC.BINANCE",
"interval": "1m",
"timestamp": 1709121060000,
"open": 51234.50,
"high": 51320.00,
"low": 51180.25,
"close": 51298.75,
"volume": 142.5,
"raw": { ... }
}
// Ticker / Quote
{
"type": "ticker",
"market": "US",
"symbol": "TSLA.US",
"timestamp": 1709121001000,
"last": 198.23,
"bid": 198.22,
"ask": 198.24,
"bid_size": 300,
"ask_size": 500,
"volume": 45230000,
"raw": { ... }
}
Symbol Namespace Convention
TickDB uses a dot-separated symbol namespace that encodes both the instrument and its market:
{symbol}.{venue}
Examples:
AAPL.US → Apple Inc, US equity (SIP)
0700.HK → Tencent Holdings, HK equity (HKEX)
BTC.BINANCE → Bitcoin, Spot Binance
ETH-USDT.BINANCE → Ethereum/USDT perpetuals, Binance Futures
This namespace convention enables unambiguous routing and allows your application to parse market context directly from the symbol string.
Timezone Standardization: Eliminating the Reconciliation Nightmare
Why Timestamps Break in Multi-Market Systems
Timezone handling is the most insidious source of bugs in multi-market data systems. Consider the following failure modes:
Daylight saving transitions: US markets operate on Eastern Time with DST transitions. When DST ends, the market opens at 9:30 AM ET—which shifts from UTC-4 to UTC-5. A naive timestamp comparison during this window produces 1-hour offsets.
Exchange-specific epoch references: Some exchanges timestamp relative to their own session open. Others use local exchange time. Others use UTC. Mixing them without normalization produces silent data corruption.
Holiday and session boundary edge cases: Lunar New Year affects HKEX but not US markets. Christmas affects US but not crypto. A system that assumes calendar alignment across markets will misalign data.
TickDB's Timestamp Normalization Strategy
TickDB normalizes all timestamps to Unix milliseconds in UTC before they reach the unified gateway. This is achieved through a three-step pipeline within each protocol adapter:
class TimestampNormalizer:
"""Normalize exchange-specific timestamps to Unix ms UTC."""
# Exchange-specific epoch offsets and DST handling rules
EXCHANGE_RULES = {
"US": {
"epoch": "midnight NYSE",
"tz": "America/New_York",
"dst_aware": True
},
"HK": {
"epoch": "midnight HKEX",
"tz": "Asia/Hong_Kong",
"dst_aware": False # HK does not observe DST
},
"CRYPTO": {
"epoch": "UTC",
"tz": "UTC",
"dst_aware": False
}
}
def normalize(self, exchange_ts, exchange_id, msg_type):
rules = self.EXCHANGE_RULES[exchange_id]
# Step 1: Parse to naive datetime using exchange's local rules
naive_dt = self._parse(exchange_ts, rules)
# Step 2: Localize with DST awareness
tz = pytz.timezone(rules["tz"])
localized_dt = tz.localize(naive_dt, is_dst=None)
# Step 3: Convert to Unix milliseconds UTC
return int(localized_dt.timestamp() * 1000)
The critical insight is that normalization happens at the adapter layer, before the message enters the unified gateway. By the time data reaches your application, every timestamp is comparable without further conversion.
Multi-Market Subscription Model
The Unified Subscription Protocol
TickDB exposes a single WebSocket endpoint that accepts a unified subscription command. Your application specifies which markets and symbols you want—without caring about the underlying protocol differences.
import os
import json
import time
import random
import websocket # pip install websocket-client
# ─────────────────────────────────────────────────────────────
# Production-grade TickDB WebSocket client with multi-market
# subscription support.
#
# Features:
# - Unified subscription across US, HK, and CRYPTO markets
# - Exponential backoff + jitter on reconnection
# - Heartbeat / ping-pong keepalive
# - Rate-limit handling (3001 + Retry-After)
# - API key loaded from environment variable
#
# ⚠️ For production HFT workloads, use aiohttp/asyncio
# ─────────────────────────────────────────────────────────────
TICKDB_WS_URL = "wss://stream.tickdb.ai/v1/market/stream"
API_KEY = os.environ.get("TICKDB_API_KEY")
if not API_KEY:
raise ValueError("TICKDB_API_KEY environment variable is not set")
def subscribe_to_markets(ws, symbols):
"""
Send a unified subscription message for multiple markets.
TickDB normalizes all responses to the Unified Data Model.
"""
subscribe_msg = {
"cmd": "subscribe",
"params": {
"channels": ["depth", "trade"],
"symbols": symbols
# No need to specify market — inferred from symbol namespace
# AAPL.US → US, 0700.HK → HK, BTC.BINANCE → CRYPTO
}
}
ws.send(json.dumps(subscribe_msg))
print(f"✓ Subscribed to {len(symbols)} symbols across markets")
def on_message(ws, message):
"""Handle incoming normalized market data."""
data = json.loads(message)
msg_type = data.get("type")
symbol = data.get("symbol")
timestamp = data.get("timestamp")
if msg_type == "depth":
# Unified depth snapshot — bids/asks always present
bids = data.get("bids", [])
asks = data.get("asks", [])
print(f"[{timestamp}] {symbol} depth: "
f"{len(bids)} bids, {len(asks)} asks")
elif msg_type == "trade":
price = data.get("price")
qty = data.get("quantity")
side = data.get("side")
print(f"[{timestamp}] {symbol} {side}: {qty} @ {price}")
else:
# System messages: ack, error, heartbeat response
print(f"[system] {data}")
def on_error(ws, error):
print(f"WebSocket error: {error}")
def on_close(ws, close_status_code, close_msg):
print(f"Connection closed: {close_status_code} — {close_msg}")
def on_open(ws):
"""On connection open, subscribe to our multi-market watchlist."""
# Example watchlist: US equity, HK equity, crypto
symbols = [
"AAPL.US",
"NVDA.US",
"0700.HK",
"9988.HK",
"BTC.BINANCE",
"ETH.BINANCE"
]
subscribe_to_markets(ws, symbols)
def run_with_reconnect():
"""
WebSocket client with exponential backoff + jitter reconnection.
Handles rate limits (3001) via Retry-After header parsing.
"""
base_delay = 1.0
max_delay = 30.0
retry_count = 0
while True:
try:
ws = websocket.WebSocketApp(
f"{TICKDB_WS_URL}?api_key={API_KEY}",
on_message=on_message,
on_error=on_error,
on_close=on_close,
on_open=on_on_open,
)
# Heartbeat: send ping every 30 seconds
def send_ping(_):
ws.send(json.dumps({"cmd": "ping"}))
# Schedule periodic heartbeat
import threading
ping_thread = threading.Thread(target=lambda: (
[ws.send(json.dumps({"cmd": "ping"}), time.sleep(30))
for _ in iter(lambda: not ws.sock or not ws.sock.connected, None)]
))
ping_thread.daemon = True
ping_thread.start()
ws.run_forever(ping_interval=None, ping_payload="ping")
except websocket.WebSocketTimeoutException:
print("Connection timed out — reconnecting...")
except Exception as e:
print(f"Unexpected error: {e}")
# Exponential backoff with jitter
delay = min(base_delay * (2 ** retry_count), max_delay)
jitter = random.uniform(0, delay * 0.1)
sleep_time = delay + jitter
print(f"Reconnecting in {sleep_time:.2f}s (attempt {retry_count + 1})")
time.sleep(sleep_time)
retry_count += 1
if __name__ == "__main__":
print("TickDB Unified Multi-Market WebSocket Client")
print(f"Connecting to: {TICKDB_WS_URL}")
run_with_reconnect()
What the Subscription Handles Internally
When you send the subscription message above, the unified gateway performs the following operations:
- Symbol parsing: Extracts market context from the symbol namespace (
AAPL.US→ US,0700.HK→ HK,BTC.BINANCE→ CRYPTO). - Adapter routing: Routes each symbol to the appropriate protocol adapter.
- Channel multiplexing: Merges the
depthandtradechannels from each adapter into a single stream. - Sequence alignment: Ensures messages are emitted in timestamp order across all adapters.
- Serialization: Encodes the unified data model as JSON and pushes to your connection.
Your application receives a single, consistent stream—regardless of how many markets or symbols you subscribed to.
Production Deployment Considerations
Connection Capacity and Scaling
A single WebSocket connection to TickDB can handle subscriptions across all supported markets simultaneously. However, practical limits apply:
| Metric | Limit |
|---|---|
| Max symbols per connection | 200 |
| Max message rate per connection | 10,000 msg/sec |
| Recommended concurrent connections (enterprise) | 1–5 |
| Heartbeat interval | 30 seconds |
| Idle timeout | 60 seconds |
For strategies requiring higher message throughput, distribute symbol subscriptions across multiple connections. TickDB's authentication model supports multiple concurrent connections per API key.
Error Code Handling
The unified gateway surfaces standardized error codes regardless of the underlying exchange:
| Code | Meaning | Action |
|---|---|---|
| 1001 / 1002 | Invalid or missing API key | Verify TICKDB_API_KEY environment variable |
| 2002 | Symbol not found | Check symbol namespace format; verify via /v1/symbols/available |
| 3001 | Rate limit exceeded | Respect Retry-After header; implement client-side throttling |
Why Unified Matters: A Comparative View
The following table compares the operational complexity of multi-market data acquisition with fragmented exchange-specific APIs versus TickDB's unified gateway:
| Capability | Fragmented Approach | TickDB Unified Gateway |
|---|---|---|
| Connections to manage | N (one per exchange) | 1 |
| Authentication mechanisms | N different schemes | Single API key |
| Timestamp normalization | DIY per exchange | Automatic (UTC ms) |
| Symbol format | Exchange-specific | Dot-namespace standard |
| Depth levels (max) | Varies by exchange | US L1 / HK L1–L10 / Crypto L1–L10 |
| Message format | Exchange-specific binary/JSON | Unified JSON schema |
| Reconnection logic | N implementations | Single production-grade client |
| Historical data | Separate endpoints per exchange | Single /kline endpoint for all |
Deployment Guide by User Segment
| User Type | Recommended Configuration | Notes |
|---|---|---|
| Individual quant developer | Single connection, up to 50 symbols | Free tier; WebSocket only |
| Active trader / small fund | 1–2 connections, 50–100 symbols | Paid tier; WebSocket + REST |
| Institutional team | 3–5 connections, full symbol universe | Enterprise tier; dedicated support, SLA |
| AI tooling integration | Single connection, specific watchlist | Install tickdb-market-data SKILL on ClawHub |
Closing: One Connection, Every Market
The core insight driving TickDB's unified gateway design is that market data is a commodity—but the engineering complexity of integrating it is not. Every hour spent maintaining exchange-specific adapters is an hour not spent on strategy development.
By normalizing protocol differences at the gateway layer, standardizing timestamps to a single reference frame, and exposing everything through a unified subscription model, TickDB collapses the multi-market integration problem from a distributed systems challenge into a single WebSocket connection.
Whether you are monitoring earnings-driven order flow in US equities, tracking depth changes in HK-listed tech stocks, or watching BTC funding rate oscillations on Binance—the data arrives in the same format, at the same time, on the same connection.
Next Steps
If you are an individual quant developer building a multi-market strategy, start with TickDB's free tier. Set your TICKDB_API_KEY environment variable, copy the WebSocket client code from this article, and subscribe to your first multi-market watchlist today.
If you need historical OHLCV data for cross-market backtesting, reach out to enterprise@tickdb.ai for institutional plans covering 10+ years of US equity data.
If you use AI coding assistants, search for and install the tickdb-market-data SKILL in your AI tool's marketplace to get TickDB integration scaffolding auto-generated for your projects.
If you want a deeper look at the depth channel's capabilities—including how buy/sell pressure ratios are computed in real time—see our companion article on order book analysis with the depth channel.
This article does not constitute investment advice. Markets involve risk; past performance does not guarantee future results.