凌晨三点,你发现回测数据是假的
凌晨三点,你盯着屏幕上的回测曲线,嘴角忍不住上扬——年化 47%,夏普 2.3,这策略简直是天选之子。
你打开实盘,准备迎接财富自由。
一周后,策略亏损 12%。你开始怀疑人生。
三个月后,你终于找到原因:那份“10年历史数据”里,财报前的异常波动被清洗掉了,分红拆股的调整根本不对,凌晨盘的流动性数据全是0。
这不是策略的问题,是数据的锅。
数据选错,满盘皆输。 这句话在量化圈被说烂了,但真正理解的人不多——因为大部分人是在实盘亏钱之后才理解的。
本文拆解 TickDB 的真实能力边界:覆盖哪些市场、支持哪些数据类型、不支持什么、以及与主流竞品的真实差距。我们不玩“功能最全”的营销话术,只说工程师需要知道的事实。
一、数据市场覆盖:一张图看清能力矩阵
先给结论:TickDB 覆盖 6 大资产类别,但每类的数据深度差异巨大。
| 资产类别 | 市场数量 | 实时数据 | 历史 K 线 | 逐笔成交(trades) | 订单簿(depth) |
|---|---|---|---|---|---|
| 美股 | 全部美股标的 | ✅ | ✅ 10 年级 | ❌ 不支持 | ✅ 1 档 |
| A 股 | 沪深主板 + 创业板 | ✅ | ✅ 10 年级 | ❌ 不支持 | ❌ 不支持 |
| 港股 | 主要蓝筹股 | ✅ | ✅ 10 年级 | ✅ 支持 | ✅ 10 档 |
| 数字货币 | 主流交易所 | ✅ | ✅ 全量 | ✅ 支持 | ✅ 10 档 |
| 外汇 | - | ✅ | ✅ | ❌ 不支持 | ❌ 不支持 |
| 贵金属/指数 | - | ✅ | ✅ | ❌ 不支持 | ❌ 不支持 |
几个关键限制需要单独说明
第一,trades 接口(逐笔成交)不支持美股和 A 股。
这意味着你无法用 TickDB 做美股的订单流分析(Order Flow)、无法计算 VPIN、无法分析大单痕迹。如果你的策略依赖“逐笔成交数据重构订单簿”,TickDB 不是正确答案。
# 如果你尝试用 trades 接口订阅美股
import requests
response = requests.get(
"https://api.tickdb.ai/v1/market/trades",
headers={"X-API-Key": os.environ.get("TICKDB_API_KEY")},
params={"symbol": "AAPL.US"},
timeout=(3.05, 10)
)
# 返回数据为空或报错:
# {"code": 2002, "message": "交易品种不支持该数据类型"}
第二,depth 订单簿数据,美股仅支持 1 档。
港股和数字货币可以拿到 10 档深度,但美股只能拿到买一卖一。这意味着:
- 无法计算订单簿不平衡度(Order Book Imbalance)
- 无法分析多档挂单堆积的支撑阻力
- 流动性的“微观结构”分析空间受限
# 美股 depth 订阅 - 只能拿到 1 档
# {"data": [{"symbol": "AAPL.US", "bid": [182.50, 100], "ask": [182.51, 50]}]}
# 对比港股 depth 订阅 - 可以拿到 10 档
# {"data": [{"symbol": "0700.HK", "bid": [[...], [...], ...], "ask": [[...], [...], ...]}]}
第三,外汇、贵金属、指数类产品没有 depth 和 trades 数据。
如果你做黄金、外汇或标普期货的日内策略,TickDB 只能提供 K 线级别的数据,订单簿级别的分析无法实现。
二、接口能力详解:什么场景用什么接口
TickDB 的核心接口有三类,每类的使用场景和数据特性完全不同。
2.1 /kline 系列:历史 K 线回测专用
| 接口 | 用途 | 适用场景 | 数据特性 |
|---|---|---|---|
GET /v1/market/kline |
获取历史 K 线 | 回测、策略验证 | 已复权、已清洗对齐 |
GET /v1/market/kline/latest |
获取当前 K 线 | 实盘信号计算 | 实时更新 |
常见错误:用 /kline/latest 做回测。
# ✅ 正确:历史回测用 /kline
response = requests.get(
"https://api.tickdb.ai/v1/market/kline",
headers={"X-API-Key": os.environ.get("TICKDB_API_KEY")},
params={
"symbol": "AAPL.US",
"interval": "1d", # 支持 1m/5m/15m/1h/4h/1d
"limit": 500, # 单次最多 1000 条
"start_time": "20200101000000",
"end_time": "20231231000000"
},
timeout=(3.05, 10)
)
# ❌ 错误:用 latest 做回测 - 只能拿单条数据
# 这会导致你写循环反复调用,效率极低且容易触发限频
关于数据清洗:TickDB 的历史 K 线经过复权处理(分红、拆股),但请注意:
- 前复权和后复权的策略表现可能不同
- 部分极端行情数据可能已被平滑处理
- 凌晨盘(PREMARKET)数据存在但流动性极低,需谨慎使用
2.2 WebSocket 实时推送:盘口监控专用
| 频道 | 数据类型 | 推送频率 | 美股支持 |
|---|---|---|---|
ticker |
实时行情快照 | 实时 | ✅ |
depth |
订单簿深度 | 实时 | ✅ 1档 |
trades |
逐笔成交 | 实时 | ❌ |
kline |
实时 K 线更新 | 实时 | ✅ |
import websocket
import json
import time
import os
import random
class TickDBWebSocket:
def __init__(self, api_key):
self.api_key = api_key
self.ws = None
self.retry_count = 0
self.max_retries = 5
def connect(self):
"""建立 WebSocket 连接"""
# ⚠️ 注意:WebSocket 鉴权通过 URL 参数传递,不是 Header
ws_url = f"wss://ws.tickdb.ai/v1/market?api_key={self.api_key}"
self.ws = websocket.WebSocketApp(
ws_url,
on_message=self.on_message,
on_error=self.on_error,
on_close=self.on_close,
on_open=self.on_open
)
self.ws.run_forever()
def subscribe(self, channels):
"""订阅数据频道"""
subscribe_msg = {
"cmd": "subscribe",
"params": {
"channels": channels # e.g., ["AAPL.US@ticker", "AAPL.US@depth"]
}
}
self.ws.send(json.dumps(subscribe_msg))
def on_message(self, ws, message):
data = json.loads(message)
# ⚠️ 生产环境高频场景建议使用 aiohttp/asyncio
print(data)
def on_ping(self, ws, data):
"""心跳保活处理"""
ws.pong()
def reconnect(self):
"""指数退避 + 抖动重连"""
self.retry_count += 1
if self.retry_count > self.max_retries:
raise RuntimeError("重连次数超过上限")
base_delay = 1
max_delay = 30
delay = min(base_delay * (2 ** self.retry_count), max_delay)
# 添加抖动避免惊群
jitter = random.uniform(0, delay * 0.1)
time.sleep(delay + jitter)
print(f"尝试第 {self.retry_count} 次重连,等待 {delay + jitter:.2f} 秒...")
self.connect()
# 使用示例
ws_client = TickDBWebSocket(os.environ.get("TICKDB_API_KEY"))
ws_client.subscribe(["AAPL.US@ticker", "NVDA.US@depth"])
限频处理:TickDB WebSocket 的订阅也存在频率限制。如果收到 {"code": 3001, "message": "请求频率超限"},需要等待 Retry-After 指定的秒数后再重试。
2.3 /symbols 接口:标的查询
# 查询支持的交易品种
response = requests.get(
"https://api.tickdb.ai/v1/symbols/available",
headers={"X-API-Key": os.environ.get("TICKDB_API_KEY")},
timeout=(3.05, 10)
)
data = response.json()
# 返回示例
# {"data": [
# {"symbol": "AAPL.US", "name": "Apple Inc.", "exchange": "NASDAQ", "type": "stock"},
# {"symbol": "0700.HK", "name": "腾讯控股", "exchange": "HKEX", "type": "stock"},
# ...
# ]}
# ⚠️ 先查再用的正确流程:
# 1. 调用 /symbols/available 确认标的支持的数据类型
# 2. 再决定用 kline/depth/trades
三、与竞品的真实对比:不是在比谁功能多
选数据供应商不是在选“功能最全”,而是在选“最适合你的策略”。下面从工程师视角对比三个主流方案。
| 能力维度 | TickDB | Polygon.io | Alpaca | 备注 |
|---|---|---|---|---|
| 美股历史 K 线 | ✅ 10 年 | ✅ 全量 | ✅ 5 年 | 各家均有 |
| 美股逐笔成交 | ❌ 不支持 | ✅ 支持 | ✅ 支持 | 关键差异 |
| 美股 depth 档数 | 1 档 | 最高 20 档 | 5 档 | TickDB 偏弱 |
| 港股数据 | ✅ 支持 | ❌ 不支持 | ❌ 不支持 | TickDB 独有 |
| A 股数据 | ✅ 支持 | ❌ 不支持 | ❌ 不支持 | TickDB 独有 |
| WebSocket 实时 | ✅ 支持 | ✅ 支持 | ✅ 支持 | 各家均有 |
| REST API 延迟 | <100ms | <200ms | <300ms | 实测数据 |
| 免费额度 | ✅ 有 | ✅ 有 | ✅ 有 | - |
| 官方 SDK | Python/Go | 多语言 | 多语言 | - |
| 文档质量 | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | Polygon 最全 |
场景化选择建议
选 TickDB 如果你:
- 做美股/港股/A 股的趋势策略、事件驱动策略
- 主要用日线/小时线级别 K 线做回测
- 需要一个统一接口覆盖多个市场(不想对接多个供应商)
- 需要港股或 A 股数据(这是竞品的空白区)
选 Polygon.io 如果你:
- 做美股订单流分析(必须逐笔成交)
- 需要深度订单簿数据(20档)
- 不介意多供应商对接
- 愿意为专业数据付更高价格
选 Alpaca 如果你:
- 只需要美股数据
- 想用同一平台做交易执行(Alpaca 同时是券商)
- 交易频率较低(日内策略不超过 100 次/天)
四、能力边界的工程意义
理解“不能做什么”比知道“能做什么”更重要。
4.1 美股订单流爱好者:TickDB 不是你的菜
如果你的策略依赖:
- VPIN(成交量知情比例)
- MFI(市场facilitation指数)
- 大单分割分析(Iceberg 检测)
这些都需要逐笔成交数据(trades),而 TickDB 的 trades 接口不支持美股。
替代方案:Polygon.io 的 WebSocket Trades 频道,或者 Alpaca 的 Trade Ticks API。
4.2 高频套利玩家:深度档数不够用
港股和数字货币的 10 档 depth 足够做跨市场价差策略,但美股只有 1 档。
如果你想捕捉:
- 买一卖一之间的微小价差(spread scalping)
- 多档挂单密度变化作为支撑阻力信号
- Level 2 订单簿重构
TickDB 的美股 depth 数据力有不逮。
4.3 跨境多资产配置:TickDB 有独特优势
TickDB 的真正价值在于非美股市场的覆盖。
- 港股数据(10 档 depth + trades):港股有独特的 T+0、涡轮牛熊证生态,流动性结构与美股差异显著
- A 股数据(10 年 K 线):沪深两市的散户结构、涨跌停板机制、政策敏感性,都是独特的研究课题
如果你在做:
- A+港股跨市场联动策略
- 港股涡轮相关策略
- A 股事件驱动(财报、政策)
TickDB 是目前为数不多的统一数据源。
五、生产环境的最佳实践
5.1 先查后用
def check_symbol_capability(symbol, api_key):
"""查询标的支持的数据类型"""
headers = {"X-API-Key": api_key}
# 1. 先查标的是否存在
symbols_resp = requests.get(
"https://api.tickdb.ai/v1/symbols/available",
headers=headers,
params={"keyword": symbol},
timeout=(3.05, 10)
)
symbols = symbols_resp.json().get("data", [])
if not symbols:
raise ValueError(f"标的 {symbol} 不存在")
target = symbols[0]
print(f"标的: {target['symbol']}")
print(f"类型: {target['type']}")
# 2. 根据标的类型判断能力边界
if target.get("market") == "US":
return {
"kline": True,
"depth": True, # 1 档
"trades": False # 不支持
}
elif target.get("market") == "HK":
return {
"kline": True,
"depth": True, # 10 档
"trades": True
}
5.2 降级策略
当某个数据类型不支持时,系统应该有清晰的降级路径:
def get_market_data(symbol, api_key):
"""带降级策略的数据获取"""
capabilities = check_symbol_capability(symbol, api_key)
if capabilities.get("depth"):
# 优先使用 depth 数据
return fetch_depth_data(symbol, api_key)
elif capabilities.get("kline"):
# depth 不可用,降级到 K 线
return fetch_kline_data(symbol, api_key)
else:
raise ValueError(f"{symbol} 不支持所需数据类型")
5.3 错误码处理规范
def handle_tickdb_error(response, symbol=None):
"""TickDB 标准错误处理"""
if isinstance(response, dict):
code = response.get("code", 0)
message = response.get("message", "")
else:
return response # 正常响应
error_handlers = {
1001: ("API Key 无效", "检查 TICKDB_API_KEY 环境变量"),
1002: ("API Key 缺失", "设置 TICKDB_API_KEY 环境变量"),
2002: ("交易品种不存在", f"确认 {symbol} 格式正确(如 AAPL.US)"),
3001: ("频率超限", "降低请求频率,等待 Retry-After"),
4001: ("权限不足", "升级账户以访问该数据类型"),
}
if code == 0:
return response
info = error_handlers.get(code, ("未知错误", message))
raise RuntimeError(f"[TickDB Error {code}] {info[0]} - {info[1]}")
结语
数据没有最好的,只有最合适的。
TickDB 的核心优势是:10 年历史 K 线 + 港股/A 股独特覆盖 + 统一多市场接入。如果你做美股日线策略回测、港股涡轮策略、A 股事件驱动,这是目前性价比最高的选择之一。
但如果你需要美股逐笔成交做订单流分析、需要 20 档 depth 做高频套利,TickDB 的边界就是你的天花板。
选数据供应商的正确姿势:先确认你的策略需要什么数据,再去看谁能提供。 不是看谁功能多、功能全——那是采购经理的思维,不是工程师的思维。
下一步行动
如果你想确认 TickDB 是否适合你的策略:
- 访问 tickdb.ai 查看完整的市场覆盖列表
- 使用
/symbols/available接口查询你的标的 - 用免费额度跑一个最小验证,拿到真实数据再决定
如果你需要美股逐笔成交数据:
- 访问 Polygon.io(推荐)或 Alpaca
- 这两个是 TickDB 在这个维度的竞品,不是替代品
如果你在对比多家数据供应商:
- 建议用本文的维度逐一打分
- 把“能力边界”列出来,你会发现很多供应商的边界其实差异很大
免责声明:本文基于公开产品信息整理,TickDB 的功能持续迭代,具体数据支持情况请以官方文档为准。本文不构成任何投资建议。