2. Tick数据获取与存储:常见数据源介绍

做量化交易的朋友都知道,Tick数据是订单流分析的命根子。没有高质量的数据,再牛的策略也是空中楼阁。今天我就把这块内容掰开了讲,从数据源到存储,一条龙说清楚。

2.1 常见数据源介绍

数据源这块,说白了就两条路:要么直接对接交易所,要么找第三方数据商。我两种都折腾过,各有各的坑。

2.1.1 交易所API

直接连交易所,听起来很酷对吧?但这里面的门道不少。

  • 实时数据:WebSocket接口,延迟低,适合高频策略
  • 历史数据:REST接口,但通常有长度限制
  • 费用:大部分免费,但有些交易所要收数据费
注意:交易所API的限频策略很严格。我曾经在回测时没注意,一口气拉了3年的数据,结果IP被ban了整整24小时。嗯,那天的复盘计划全泡汤了。

举个例子,用Binance的API拉取BTC/USDT的Tick数据:

import requests
import json

# 获取最近1000条成交记录
url = "https://api.binance.com/api/v3/trades"
params = {
    "symbol": "BTCUSDT",
    "limit": 1000
}
response = requests.get(url, params=params)
trades = response.json()

# 看看数据结构
print(trades[0])
# 输出:{'id': 123456, 'price': '50000.00', 'qty': '0.01', 
#        'time': 1623456789000, 'isBuyerMaker': True}

2.1.2 第三方数据商

如果你不想自己折腾交易所API,第三方数据商是个省心的选择。我个人的习惯是,小规模回测用免费数据,实盘或大规模研究才买付费数据。

数据商 覆盖范围 数据质量 价格
QuantConnect 美股、期货、加密货币 免费/付费
Polygon.io 美股为主 月费制
Kaiko 加密货币 极高 企业级定价
CoinAPI 多交易所加密货币 按量计费
我的建议:刚开始做研究,先用免费数据跑通流程。等策略有眉目了,再考虑买付费数据。别一上来就花大钱,我见过太多人数据买了,策略却没跑出来。

2.2 数据存储格式选择

数据拿到手了,存哪里?怎么存?这问题看似简单,但选错了后面会非常痛苦。你想想看,几千万条Tick数据,如果存成CSV,加载一次就要等半天。

2.2.1 CSV格式

CSV是最通用的格式,但也是最慢的。适合小规模数据或临时分析。

import pandas as pd

# 保存为CSV
df.to_csv('tick_data.csv', index=False)

# 读取CSV
df = pd.read_csv('tick_data.csv', parse_dates=['timestamp'])
避坑指南:我曾经用CSV存了3个月的Tick数据,文件大小超过10GB。每次读取都要等5分钟,而且经常内存溢出。后来我果断换成了Parquet,读取时间从5分钟降到了10秒。

2.2.2 Parquet格式

Parquet是列式存储格式,压缩率高,读取快。我个人强烈推荐用于Tick数据存储。

# 保存为Parquet
df.to_parquet('tick_data.parquet', compression='snappy')

# 读取Parquet
df = pd.read_parquet('tick_data.parquet')

# 按日期分区存储,查询更快
df['date'] = df['timestamp'].dt.date
df.to_parquet('tick_data_partitioned.parquet', 
              partition_cols=['date'])

2.2.3 HDF5格式

HDF5适合存储大规模科学数据,支持多维数组。但说实话,在量化领域用得不多。

# 保存为HDF5
df.to_hdf('tick_data.h5', key='trades', mode='w')

# 读取HDF5
df = pd.read_hdf('tick_data.h5', key='trades')

2.3 本地数据库搭建

当数据量达到TB级别时,文件存储就不够用了。这时候需要上数据库。我建议从小规模开始,用SQLite就够了。

2.3.1 SQLite

SQLite是轻量级数据库,零配置,适合单机使用。对于个人研究来说,完全够用。

import sqlite3
import pandas as pd

# 创建数据库连接
conn = sqlite3.connect('tick_data.db')

# 创建表
conn.execute('''
    CREATE TABLE IF NOT EXISTS trades (
        id INTEGER PRIMARY KEY,
        symbol TEXT,
        price REAL,
        volume REAL,
        timestamp INTEGER,
        side TEXT
    )
''')

# 批量插入数据
df.to_sql('trades', conn, if_exists='append', index=False)

# 查询数据
query = '''
    SELECT * FROM trades 
    WHERE symbol = 'BTCUSDT' 
    AND timestamp BETWEEN 1623456789000 AND 1623456889000
'''
result = pd.read_sql(query, conn)
小技巧:给timestamp字段加索引,查询速度能提升10倍以上。我刚开始没加索引,查一次数据要等30秒,加了索引后秒出结果。

2.3.2 InfluxDB

如果你做的是高频交易,时间序列数据量特别大,InfluxDB是更好的选择。它是专门为时序数据设计的数据库。

from influxdb import InfluxDBClient
import pandas as pd

# 连接InfluxDB
client = InfluxDBClient(host='localhost', port=8086)
client.create_database('tick_data')
client.switch_database('tick_data')

# 构造数据点
json_body = [
    {
        "measurement": "trades",
        "tags": {
            "symbol": "BTCUSDT"
        },
        "time": "2023-01-01T00:00:00Z",
        "fields": {
            "price": 50000.00,
            "volume": 0.01,
            "side": "buy"
        }
    }
]

# 写入数据
client.write_points(json_body)

# 查询数据
results = client.query('SELECT * FROM trades WHERE symbol = \'BTCUSDT\'')
df = pd.DataFrame(results.get_points())
核心要点:选择存储方案时,记住这个原则——
- 数据量 < 1GB:CSV或SQLite
- 数据量 1GB-100GB:Parquet
- 数据量 > 100GB:InfluxDB或分布式存储

好了,数据源和存储这块就讲到这里。记住,数据是量化交易的基石,花时间把这块做好,后面会省很多事。我个人踩过的坑,都写在上面了,希望能帮你少走弯路。

Tick数据获取与存储知识体系 数据源 交易所API WebSocket/REST 第三方数据商 QuantConnect等 实时数据 + 历史数据 存储格式 CSV 通用但慢 Parquet 列式存储 HDF5 科学数据 按数据量选择 本地数据库 SQLite 轻量级,零配置 适合单机 < 100GB InfluxDB 时序数据库 适合高频 > 100GB