数据质量评估:三大核心检查

做市库存数据,说白了就是你的交易命根子。

数据脏了,策略再好也是白搭。我见过太多团队,模型跑得飞起,结果一查数据全是坑。今天咱们就聊聊数据质量评估这件事,我把它拆成三个维度:完整性、准确性、一致性。

核心观点:数据清洗不是一次性工作,而是贯穿做市全流程的持续动作。每次数据入库,都要过这三关。

一、数据完整性检查:缺失值比例

先问个问题:你的数据表里,有多少空值?

很多人觉得缺失几个值无所谓,但做市交易里,一个缺失的 tick 数据可能让你错过最佳报价时机。我个人习惯,每次拿到新数据源,第一件事就是跑缺失值统计。

1.1 缺失值类型

  • 完全随机缺失:比如网络抖动丢了一个包,这种影响相对小
  • 随机缺失:跟其他字段有关,比如大单成交时行情推送延迟
  • 非随机缺失:最危险的一种。比如涨跌停时数据不更新,这种缺失本身就有信息量

注意:涨跌停期间的缺失值,千万别直接填充!我曾经踩过这个坑,用前向填充把涨停价填成了正常交易价,回测结果直接翻车。

1.2 缺失值评估指标

指标 计算公式 阈值建议
字段缺失率 缺失数 / 总记录数 < 5% 可接受,> 20% 需排查
连续缺失长度 连续缺失的 tick 数 做市数据 < 3 个 tick
时间窗口缺失率 每 5 分钟窗口内的缺失比例 < 1%
# 我常用的缺失值检查代码
import pandas as pd
import numpy as np

def check_missing_quality(df, threshold=0.05):
    """
    数据完整性检查
    """
    # 字段级别缺失率
    missing_ratio = df.isnull().mean()
    print("字段缺失率:")
    print(missing_ratio[missing_ratio > 0])
    
    # 连续缺失检测
    for col in ['bid_price', 'ask_price', 'last_price']:
        if col in df.columns:
            consecutive_missing = df[col].isnull().astype(int).groupby(
                (df[col].notnull()).cumsum()
            ).cumsum()
            max_consecutive = consecutive_missing.max()
            if max_consecutive > 3:
                print(f"警告:{col} 存在连续 {max_consecutive} 个缺失值")
    
    # 时间窗口缺失率
    df['time_window'] = df['timestamp'].dt.floor('5min')
    window_missing = df.groupby('time_window').apply(
        lambda x: x.isnull().mean()
    )
    
    return missing_ratio, window_missing

实战经验:做市数据里,bid/ask 的缺失往往比 last_price 更致命。因为报价缺失意味着你无法判断当前市场深度,策略会直接瘫痪。

二、数据准确性校验:价格跳变与涨跌停异常

数据不缺了,但数据对吗?

嗯,这里要注意。价格跳变和涨跌停异常,是做市数据里最常见的两个坑。我记得有一次,某个品种的 tick 数据里突然出现一个 99999 的价格,明显是交易所的异常报文。如果没过滤掉,策略会直接报出天价单。

2.1 价格跳变检测

什么叫价格跳变?就是相邻两个 tick 之间,价格变化幅度远超正常范围。

  • 绝对跳变:价格变化超过 N 个最小变动价位
  • 相对跳变:价格变化比例超过阈值(比如 1%)
  • 回跳检测:价格跳变后又迅速恢复,这种往往是数据错误
def detect_price_jumps(df, price_col='last_price', threshold=0.01):
    """
    检测价格跳变
    threshold: 相对变化阈值,默认 1%
    """
    # 计算价格变化率
    price_changes = df[price_col].pct_change()
    
    # 标记跳变点
    jump_mask = price_changes.abs() > threshold
    
    # 回跳检测:跳变后 3 个 tick 内恢复
    rollback_mask = pd.Series(False, index=df.index)
    for i in range(1, 4):
        rollback_mask |= (price_changes.shift(-i).abs() > threshold)
    
    # 综合判断
    anomaly = jump_mask & ~rollback_mask
    
    print(f"检测到 {anomaly.sum()} 个价格跳变异常")
    return anomaly

2.2 涨跌停异常处理

涨跌停的时候,数据会变得很奇怪。价格不动了,但成交量还在涨。很多新手直接把这部分数据删掉,其实不对。

关键认知:涨跌停期间的数据,反映了市场的极端情绪。直接删除会丢失重要信息,但保留又会影响统计指标。我的做法是单独标记,做策略时特殊处理。

def handle_limit_up_down(df, limit_pct=0.1):
    """
    涨跌停数据标记
    limit_pct: 涨跌停幅度,比如 10%
    """
    # 计算当日涨跌停价格
    df['daily_high'] = df.groupby(df['timestamp'].dt.date)['last_price'].cummax()
    df['daily_low'] = df.groupby(df['timestamp'].dt.date)['last_price'].cummin()
    
    # 标记涨跌停状态
    df['is_limit_up'] = (df['last_price'] >= df['daily_high'] * (1 - limit_pct * 0.01))
    df['is_limit_down'] = (df['last_price'] <= df['daily_low'] * (1 + limit_pct * 0.01))
    
    # 涨跌停期间,bid/ask 可能不更新
    df.loc[df['is_limit_up'] | df['is_limit_down'], 'data_quality'] = 'limit'
    
    return df

避坑指南:我曾经遇到过一个情况,某只股票连续涨停,但我的数据里 last_price 一直不变,导致策略以为市场没波动。后来加了涨跌停标记,才把这个问题暴露出来。

三、数据一致性核对:多源数据交叉验证

最后一个环节,也是最容易被忽视的。

你从交易所拿到的数据,和从行情商拿到的数据,对得上吗?我见过最离谱的情况,两个数据源的同一笔成交,价格差了 0.5 个 tick。这种误差在回测里可能不明显,但实盘做市时,0.5 个 tick 就是盈亏的分界线。

3.1 交叉验证维度

验证维度 检查内容 容忍误差
时间戳对齐 同一笔成交的时间是否一致 < 1ms
价格一致性 同一时刻的 bid/ask/last 是否匹配 0 误差
成交量一致性 累计成交量是否吻合 < 0.1%
订单簿快照 买卖盘口深度是否一致 允许 1 档差异

3.2 交叉验证实现

def cross_validate_data(source_a, source_b, tolerance=1e-6):
    """
    多源数据交叉验证
    """
    # 时间戳对齐
    merged = pd.merge_asof(
        source_a.sort_values('timestamp'),
        source_b.sort_values('timestamp'),
        on='timestamp',
        suffixes=('_a', '_b'),
        tolerance=pd.Timedelta('1ms')
    )
    
    # 价格一致性检查
    price_diff = abs(merged['last_price_a'] - merged['last_price_b'])
    price_errors = price_diff > tolerance
    
    # 成交量一致性检查
    vol_diff = abs(merged['volume_a'] - merged['volume_b'])
    vol_errors = vol_diff > (merged['volume_a'] * 0.001)
    
    # 汇总结果
    results = {
        'total_records': len(merged),
        'price_mismatch': price_errors.sum(),
        'volume_mismatch': vol_errors.sum(),
        'price_error_rate': price_errors.mean(),
        'volume_error_rate': vol_errors.mean()
    }
    
    return results

个人建议:交叉验证最好做成自动化脚本,每天跑一次。我团队里有个定时任务,每天早上开盘前自动跑一遍数据一致性检查,有问题直接报警。省心很多。

知识体系总览

说了这么多,咱们用一张图把整个数据质量评估的框架串起来。

数据质量评估三大核心 原始做市数据 数据完整性 缺失值比例检查 数据准确性 价格跳变 & 涨跌停 数据一致性 多源交叉验证 检查方法 • 字段缺失率统计 • 连续缺失检测 • 时间窗口分析 检查方法 • 价格跳变检测 • 涨跌停标记 • 异常值过滤 检查方法 • 时间戳对齐 • 价格/成交量比对 • 订单簿快照验证 高质量清洗数据

这张图把咱们今天讲的内容串起来了。从原始数据进来,经过完整性、准确性、一致性三道关卡,最终输出高质量数据。每一步都有对应的检查方法和代码实现。

最后说一句:数据质量评估不是一次性工作。市场在变,数据源在变,你的检查逻辑也要跟着迭代。我团队每季度会复盘一次数据质量报告,看看哪些检查项需要调整。这个习惯,建议你也养成。

蓝海数据掘金营,专注资料整理