第三章 数据工程基础:多源数据采集、数据清洗、特征对齐、时间序列处理

各位同学,欢迎来到实战课的第三讲。说实话,很多做量化的人,一上来就研究策略、调参数,结果模型跑起来全是噪音。为什么?因为数据没处理好。我见过太多团队,策略逻辑再漂亮,数据源一塌糊涂,最后回测曲线漂亮得像假的一样——嗯,其实就是假的。

今天这一章,咱们就把数据工程这个地基打牢。说白了,数据工程就是四个步骤:采集、清洗、对齐、处理。每一步都有坑,我一个个带你们踩一遍。

3.1 多源数据采集:别让数据源成为你的短板

做跨市场交易,数据源不可能只有一个。股票、期货、外汇、加密货币,每个市场的数据格式、频率、质量都不一样。我个人习惯,先把数据源分成三类:

  • 交易所官方API:最可靠,但有限流,而且有些历史数据要付费
  • 第三方数据商:比如Wind、Bloomberg、Quandl,数据全但贵
  • 爬虫抓取:免费但脏,适合辅助验证

我在项目中遇到过一个问题:同时拉取A股和美股数据,A股是tick级,美股是分钟级,时间戳格式还不一样。你想想看,如果不对齐,后面做特征工程全是错的。

核心原则:采集阶段就要统一时间基准。我建议全部转为UTC时间戳,避免时区问题。

3.2 数据清洗:脏数据是策略的毒药

数据清洗听着简单,做起来全是细节。我刚开始做量化时,觉得清洗就是去掉空值。结果有一次回测收益高得离谱,一查发现是某天数据缺失,程序自动用前值填充,导致信号连续触发。嗯,从那以后我再也不敢轻视清洗了。

常见的脏数据问题:

  1. 缺失值:不能简单删除或填充,要看上下文。比如停牌日的数据,填充前值反而合理
  2. 异常值:比如价格突然跳涨100倍,多半是数据录入错误。我习惯用3σ原则或IQR方法检测
  3. 重复数据:API重连时容易产生重复行,必须去重
  4. 时间戳错乱:比如某条数据的时间戳比前一条还早,这通常是网络延迟导致的
我的小技巧:清洗完数据后,一定要做一次「合理性校验」。比如检查最高价是否大于最低价,成交量是否为正。这些看似废话,但真能救命。

3.3 特征对齐:跨市场交易的核心难点

特征对齐,说白了就是把不同频率、不同维度的数据,放到同一个时间轴上。举个例子:你要用日线级别的宏观经济数据,去预测分钟级别的股价波动。怎么对齐?

我常用的对齐策略有三种:

对齐方式 适用场景 注意事项
前向填充 低频数据对齐到高频 避免未来信息泄露
后向填充 高频数据聚合到低频 注意聚合方式(均值/中位数)
插值法 缺失值较少的情况 线性插值可能引入偏差

我曾经犯过一个低级错误:用当天的收盘价去预测当天的涨跌。你想想看,这不就是作弊吗?特征对齐时,一定要确保所有特征都是「已知信息」,不能包含未来数据。

避坑指南:对齐时务必注意「幸存者偏差」。比如你只对齐了当前还在交易的股票,退市的股票数据全丢了,回测结果会虚高。

3.4 时间序列处理:让数据说话

时间序列处理,是量化交易的核心技能。说白了,就是把原始价格数据,变成模型能理解的「特征」。我常用的处理方式包括:

  • 差分处理:价格序列通常非平稳,差分后变成收益率序列,模型更容易学习
  • 滚动统计:比如过去20天的均值、标准差,用来刻画趋势和波动
  • 季节性分解:有些品种有明显的日间效应或周内效应,分解后能提取规律
  • 归一化/标准化:不同品种的价格量级不同,必须统一到同一尺度

这里我特别想强调一点:时间序列的划分必须严格按时间顺序。不能用未来的数据去训练模型,也不能用随机打乱的方式做交叉验证。我见过有人用K折交叉验证做时间序列,结果模型在测试集上表现极好,实盘一塌糊涂——因为时间顺序被打乱了,模型学到了「未来信息」。

3.5 知识体系总览

下面这张图,是我自己总结的数据工程核心流程。每次做新项目,我都会先过一遍这张图,确保没有遗漏。

数据工程核心流程 多源数据采集 数据清洗 特征对齐 时间序列处理 API / 第三方 / 爬虫 缺失值 / 异常值 / 重复 前向填充 / 后向填充 差分 / 滚动统计 / 归一化 迭代优化:清洗后发现问题,返回采集阶段补充数据 输出:干净、对齐、可用的特征矩阵 注意:每一步都可能需要返回上一步,数据工程是迭代过程 常见问题:未来信息泄露 | 幸存者偏差 | 时区不一致 | 数据频率不匹配

3.6 实战代码示例

光说不练假把式。下面这段代码,是我在实际项目中常用的数据清洗流程。你们可以直接拿去用,但记得改参数。

import pandas as pd
import numpy as np

def clean_market_data(df):
    """
    多市场数据清洗函数
    df: DataFrame,必须包含 'timestamp', 'open', 'high', 'low', 'close', 'volume'
    """
    # 1. 去重
    df = df.drop_duplicates(subset=['timestamp'])
    
    # 2. 时间戳排序
    df = df.sort_values('timestamp')
    
    # 3. 异常值检测(3σ原则)
    for col in ['open', 'high', 'low', 'close']:
        mean = df[col].mean()
        std = df[col].std()
        df = df[(df[col] > mean - 3*std) & (df[col] < mean + 3*std)]
    
    # 4. 合理性校验
    df = df[df['high'] >= df['low']]
    df = df[df['volume'] > 0]
    
    # 5. 缺失值处理(前向填充)
    df = df.fillna(method='ffill')
    
    return df

# 使用示例
# raw_data = pd.read_csv('market_data.csv')
# clean_data = clean_market_data(raw_data)
注意:上面的代码只是基础版本。实际项目中,我还会加入「停牌检测」、「涨跌停标记」、「复权处理」等逻辑。每个市场规则不同,千万别一刀切。

3.7 总结

数据工程这件事,说白了就是「磨刀不误砍柴工」。我见过太多人急着跑模型,结果数据质量不过关,浪费了大量时间。记住:垃圾进,垃圾出。数据工程做得好,模型训练事半功倍;做不好,再牛的算法也是白搭。

嗯,这一章的内容就到这里。你们回去之后,可以拿自己手头的数据跑一遍清洗流程,看看能发现多少问题。相信我,第一次跑完,你可能会怀疑自己之前做的策略是不是都在瞎搞——我当年就是这样。


专注资料整理