凌晨三点,你发现回测数据是假的

凌晨三点,你盯着屏幕上的回测曲线,嘴角忍不住上扬——年化 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 是否适合你的策略

  1. 访问 tickdb.ai 查看完整的市场覆盖列表
  2. 使用 /symbols/available 接口查询你的标的
  3. 用免费额度跑一个最小验证,拿到真实数据再决定

如果你需要美股逐笔成交数据

  • 访问 Polygon.io(推荐)或 Alpaca
  • 这两个是 TickDB 在这个维度的竞品,不是替代品

如果你在对比多家数据供应商

  • 建议用本文的维度逐一打分
  • 把“能力边界”列出来,你会发现很多供应商的边界其实差异很大

免责声明:本文基于公开产品信息整理,TickDB 的功能持续迭代,具体数据支持情况请以官方文档为准。本文不构成任何投资建议。