4. Tick级数据与OHLCV数据

高频交易的第一手数据源是逐笔成交明细(Tick数据),而策略回测与信号计算通常依赖压缩后的OHLCV数据。本章深入讲解Tick数据的格式与存储方案、OHLCV的生成逻辑,以及数据压缩与对齐的核心技术。

4.1 Tick数据格式与存储

Tick数据记录每一笔成交的详细信息,是高频交易最细粒度的数据源。不同交易所的Tick格式略有差异,但核心字段一致。

字段 类型 说明
Timestamp datetime 交易所撮合时间(纳秒级精度)
Price float 成交价格
Volume int 该笔成交量(股/合约)
Side char 主动成交方向(B/S)
TradeID string 交易所唯一成交编号
存储建议:高频场景下Tick数据量巨大(单只股票日均可达数十万笔),推荐使用列式存储格式(如Parquet)或时序数据库(如InfluxDB),避免使用CSV文本格式。

4.2 OHLCV数据生成

OHLCV(Open, High, Low, Close, Volume)是将Tick数据按固定时间窗口聚合后的标准金融数据形态。生成过程本质上是时间序列的降采样与统计。

import pandas as pd
import numpy as np

def tick_to_ohlcv(tick_df, freq='1min'):
    """
    将Tick级DataFrame转换为OHLCV数据
    tick_df: 必须包含 'price', 'volume', 'timestamp' 列
    freq: 聚合频率,如 '1min', '5min', '1s'
    """
    # 确保时间戳为索引
    tick_df = tick_df.set_index('timestamp').sort_index()
    
    # 使用resample进行聚合
    ohlcv = tick_df['price'].resample(freq).ohlc()
    ohlcv['volume'] = tick_df['volume'].resample(freq).sum()
    
    # 处理空值:若窗口内无成交,前向填充价格,成交量置0
    ohlcv.fillna(method='ffill', inplace=True)
    ohlcv['volume'].fillna(0, inplace=True)
    
    return ohlcv
关键逻辑:
  • Open:窗口内第一笔成交价
  • High:窗口内最高成交价
  • Low:窗口内最低成交价
  • Close:窗口内最后一笔成交价
  • Volume:窗口内所有成交量之和
Tick → OHLCV 聚合流程 Tick 数据流 逐笔成交明细 时间窗口分组 按1min/5min/1s 对齐时间戳 聚合计算 OHLC + Volume OHLCV 数据 标准K线数据 ⚠ 注意事项 空窗口需前向填充价格 成交量置0而非NaN

4.3 数据压缩与对齐

高频策略常涉及多标的、多频率的数据源,必须进行严格的时间对齐与数据压缩,避免未来函数与数据泄露。

4.3.1 数据压缩策略

压缩方式 适用场景 压缩比 信息损失
时间等频 标准K线、回测基准 高 中等(丢失微观结构)
成交量等频 成交量加权策略 中 低(保留交易活跃度)
笔数等频 订单流分析 中 低(保留订单节奏)
价格变动等频 波动率交易 低 极低(保留价格跳跃)

4.3.2 多标的时间对齐

当策略同时使用股票A的1分钟K线和股票B的Tick数据时,必须将两者对齐到统一时间轴。常用方法为向前填充(Forward Fill)与线性插值。

def align_multiple_assets(tick_dict, freq='1min'):
    """
    将多个资产的Tick数据对齐到统一OHLCV时间轴
    tick_dict: dict {asset_name: tick_df}
    """
    aligned = {}
    master_index = None
    
    # 先生成主时间轴(取所有资产时间范围的并集)
    for asset, df in tick_dict.items():
        ohlcv = tick_to_ohlcv(df, freq)
        if master_index is None:
            master_index = ohlcv.index
        else:
            master_index = master_index.union(ohlcv.index)
    
    # 对齐每个资产
    for asset, df in tick_dict.items():
        ohlcv = tick_to_ohlcv(df, freq)
        # 重采样到主时间轴,前向填充
        aligned[asset] = ohlcv.reindex(master_index).fillna(method='ffill')
        # 成交量缺失置0
        aligned[asset]['volume'].fillna(0, inplace=True)
    
    return aligned
⚠ 对齐陷阱:切勿使用未来数据填充缺失值(如bfill)。高频回测中,使用未来数据会导致策略表现虚高,实盘时完全失效。始终使用前向填充(ffill)或直接丢弃缺失窗口。
多标的统一时间轴对齐 资产A Tick 1min OHLCV 资产B Tick 5min OHLCV 资产C Tick Tick级数据 时间轴对齐 统一时间索引 前向填充缺失 成交量置0 对齐后数据 统一时间戳 无未来数据 可直接回测 ⚠ 对齐核心原则 只使用历史数据填充,禁止bfill

4.4 实战:Tick数据存储与OHLCV生成

以下代码演示完整的Tick数据存储(Parquet格式)与OHLCV生成流水线,可直接用于高频策略的数据准备阶段。

import pandas as pd
import os
from pathlib import Path

class TickDataPipeline:
    """Tick数据存储与OHLCV生成流水线"""
    
    def __init__(self, data_dir='./tick_data'):
        self.data_dir = Path(data_dir)
        self.data_dir.mkdir(parents=True, exist_ok=True)
    
    def save_tick_parquet(self, tick_df, symbol, date):
        """将Tick数据存储为Parquet,按日期分区"""
        file_path = self.data_dir / f"{symbol}_{date}.parquet"
        tick_df.to_parquet(file_path, compression='snappy')
        return file_path
    
    def load_tick_parquet(self, symbol, date):
        """加载指定日期的Tick数据"""
        file_path = self.data_dir / f"{symbol}_{date}.parquet"
        if file_path.exists():
            return pd.read_parquet(file_path)
        else:
            raise FileNotFoundError(f"数据文件不存在: {file_path}")
    
    def generate_daily_ohlcv(self, symbol, date, freq='1min'):
        """生成并存储日内的OHLCV数据"""
        tick_df = self.load_tick_parquet(symbol, date)
        ohlcv = tick_to_ohlcv(tick_df, freq)
        
        # 添加日期列便于后续查询
        ohlcv['date'] = date
        ohlcv['symbol'] = symbol
        
        # 存储OHLCV
        ohlcv_path = self.data_dir / f"{symbol}_{date}_ohlcv_{freq}.parquet"
        ohlcv.to_parquet(ohlcv_path, compression='snappy')
        return ohlcv

# 使用示例
pipeline = TickDataPipeline()
# 假设已有tick_data DataFrame
# pipeline.save_tick_parquet(tick_data, 'AAPL', '2024-01-15')
# ohlcv_1min = pipeline.generate_daily_ohlcv('AAPL', '2024-01-15', '1min')
数据流水线要点:
  • 存储层:Parquet + Snappy压缩,比CSV节省80%空间,读取速度快10倍以上
  • 分区策略:按日期+标的符号分区,便于增量更新与并行读取
  • 生成策略:支持多频率OHLCV生成,避免重复存储原始Tick
  • 对齐策略:统一时间轴 + 前向填充,确保回测无未来函数