数据采集与清洗:从原始数据到可用资产
做市场预测模型,有个残酷的现实我得先告诉你——80%的时间都花在数据准备上。模型跑起来可能就几分钟,但前面那些脏活累活,才是真正的重头戏。
我个人习惯把数据采集和清洗看作「炼油」的过程。原油不能直接烧,原始数据也不能直接喂给模型。今天咱们就聊聊,怎么把那些乱七八糟的原始数据,变成干净可用的分析素材。
数据来源:你的数据从哪来?
做量化分析,数据来源无非三条路:API、爬虫、数据库。每条路我都踩过坑,一个一个说。
1. API接口——最优雅的方式
API是官方提供的数据通道。说白了,就是数据方给你开了一扇门,你按规矩敲门就能拿到数据。
我在项目中常用的是交易所的REST API。比如获取比特币的实时价格:
import requests
import pandas as pd
# 以币安API为例
url = "https://api.binance.com/api/v3/klines"
params = {
"symbol": "BTCUSDT",
"interval": "1h",
"limit": 100
}
response = requests.get(url, params=params)
data = response.json()
# 转换成DataFrame
columns = ['timestamp', 'open', 'high', 'low', 'close', 'volume',
'close_time', 'quote_volume', 'count', 'taker_buy_vol',
'taker_buy_quote_vol', 'ignore']
df = pd.DataFrame(data, columns=columns)
print(df[['timestamp', 'open', 'high', 'low', 'close']].head())
2. 爬虫——不得已的选择
有些数据没有API,或者API收费太贵。这时候就得爬虫上场了。
但我要提醒你——爬虫有法律风险。我曾经因为爬取某财经网站的数据,被对方发了律师函。从那以后,我定了个规矩:先看robots.txt,再看是否有付费API,最后才考虑爬虫。
如果确实需要爬虫,用BeautifulSoup或Scrapy都行。但记住:控制频率,尊重数据源。
3. 数据库——老本行最稳
如果你在公司做量化,大概率数据已经存在数据库里了。MySQL、PostgreSQL、MongoDB都常见。
连接数据库的代码很简单:
import pymysql
import pandas as pd
conn = pymysql.connect(
host='localhost',
user='root',
password='your_password',
database='market_data'
)
query = "SELECT * FROM stock_daily WHERE trade_date >= '2024-01-01'"
df = pd.read_sql(query, conn)
conn.close()
数据清洗流程:从脏数据到干净数据
数据拿到手了,但别高兴太早。真实世界的数据,比你想象的脏得多。
我总结了一套清洗流程,你照着做基本不会出大问题:
- 初步探查——用df.info()和df.describe()快速了解数据概况
- 格式统一——日期格式、数值类型、列名规范
- 缺失值处理——删还是补?看情况
- 异常值检测——那些离谱的数据点,得揪出来
- 重复值去重——同一个数据出现两次,肯定有问题
- 一致性检查——比如开盘价不能高于最高价,这是常识
嗯,这六步走完,数据基本就能用了。
缺失值处理:补还是不补?
缺失值是个老生常谈的问题。但我想说,没有万能的方法,全看场景。
常见的处理方式:
| 方法 | 适用场景 | 缺点 |
|---|---|---|
| 直接删除 | 缺失比例很小(<5%) | 可能丢失有用信息 |
| 均值/中位数填充 | 数值型数据,分布较均匀 | 会降低数据方差 |
| 前向填充(ffill) | 时间序列数据 | 假设数据变化不大 |
| 插值法 | 有趋势的数据 | 计算量稍大 |
| 模型预测 | 缺失值较多且重要 | 可能引入模型偏差 |
举个例子,处理股票数据的缺失值:
# 前向填充——股票数据常用
df['close'].fillna(method='ffill', inplace=True)
# 线性插值——适合有趋势的数据
df['close'].interpolate(method='linear', inplace=True)
# 用前一天同一时间的数据填充
df['close'].fillna(df['close'].shift(1), inplace=True)
异常值处理:揪出那些「离谱」的数据
异常值,说白了就是那些「看着就不对」的数据点。比如某股票突然涨了1000%,或者成交量突然少了几个零。
为什么会这样?可能是数据录入错误,可能是系统故障,也可能是真实的市场异动。你得学会区分。
检测异常值的方法:
- 3σ原则——超过均值±3个标准差的数据,视为异常
- 箱线图法——超出1.5倍IQR的数据点
- Z-score法——标准化后绝对值大于3的
- 领域知识——比如股票涨跌幅超过10%,在A股就是异常
代码实现:
import numpy as np
# Z-score方法
def detect_outliers_zscore(data, threshold=3):
z_scores = np.abs((data - data.mean()) / data.std())
return z_scores > threshold
# 箱线图方法
def detect_outliers_iqr(data):
Q1 = data.quantile(0.25)
Q3 = data.quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
return (data < lower_bound) | (data > upper_bound)
# 应用
outliers = detect_outliers_zscore(df['close'])
print(f"发现 {outliers.sum()} 个异常值")
知识体系总览
说了这么多,咱们用一张图把整个流程串起来。你想想看,数据从采集到清洗,其实就这几步:
这张图把整个流程串起来了。你从左边选数据来源,中间走清洗流程,右边得到干净数据。下面两个子模块是清洗中的重点——缺失值和异常值处理。
说实话,数据清洗这活儿不性感,但它是所有预测模型的基石。我见过太多人急着调模型参数,结果数据里一堆坑,最后模型跑出来的结果根本没法用。
记住一句话:垃圾进,垃圾出。数据质量不过关,再牛的算法也白搭。
公众号:蓝海资料掘金营,微信deep3321