第二章:数据获取与清洗
做量化投资,第一步就是搞数据。这话听起来简单,但我在项目里见过太多人栽在这个环节上。数据不对,后面策略再牛也是白搭。今天咱们就聊聊怎么用Python把数据拿到手,再把它收拾得干干净净。
2.1 用pandas-datareader拉数据
我个人习惯用pandas-datareader来获取股票数据。这玩意儿封装好了,直接调用就行,不用自己写爬虫。
先装库:
pip install pandas-datareader
然后拉数据:
import pandas as pd
import pandas_datareader.data as web
import datetime
start = datetime.datetime(2020, 1, 1)
end = datetime.datetime(2023, 12, 31)
# 获取苹果公司股票数据
df = web.DataReader('AAPL', 'yahoo', start, end)
print(df.head())
跑完这段代码,你会得到一个DataFrame,里面有开盘价、收盘价、最高价、最低价、成交量这些字段。嗯,这里要注意,yahoo这个数据源有时候会抽风,连接不稳定。我在项目中遇到过好几次,解决方案是加个重试机制,或者换个数据源比如stooq。
2.2 数据清洗——别让脏数据坑了你
数据拉下来,你以为就能直接用了吗?太天真了。真实的数据往往千疮百孔。我见过最离谱的一次,某只股票某天的收盘价竟然是负数——这明显是数据录入错误。
常见的脏数据问题:
- 缺失值:某天没有交易,或者数据源没更新
- 异常值:价格突然跳变,比如从100块蹦到1000块
- 重复数据:同一天出现了两条记录
- 格式问题:日期格式不统一,或者数字被存成了字符串
咱们一个一个来处理。
2.2.1 缺失值处理
先看看数据里有没有缺失值:
print(df.isnull().sum())
如果有缺失,怎么补?这得看情况。我个人习惯分三种场景:
| 场景 | 处理方法 | 适用情况 |
|---|---|---|
| 少量缺失(<5%) | 向前填充(ffill) | 用前一天的数据补上 |
| 中间缺失 | 线性插值 | 用前后两天的平均值 |
| 大量缺失 | 直接删除 | 数据质量太差,留着也没用 |
代码实现:
# 向前填充
df.fillna(method='ffill', inplace=True)
# 线性插值
df.interpolate(method='linear', inplace=True)
# 删除缺失行
df.dropna(inplace=True)
2.2.2 异常值检测
异常值怎么找?我常用两种方法:
- 3σ原则:超出均值±3倍标准差的数据视为异常
- IQR方法:超出Q1-1.5*IQR或Q3+1.5*IQR的数据视为异常
代码示例:
# 用IQR方法检测异常值
Q1 = df['Close'].quantile(0.25)
Q3 = df['Close'].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
# 标记异常值
df['is_outlier'] = (df['Close'] < lower_bound) | (df['Close'] > upper_bound)
# 查看异常值
print(df[df['is_outlier']])
你想想看,如果一只股票平时波动在±5%以内,突然某天涨了20%,这大概率是数据错误,而不是真的涨了这么多。我一般会把这些异常值替换成前后两天的平均值,或者直接删除。
2.3 数据标准化——让不同股票站在同一起跑线
不同股票的价格差异很大,茅台2000块一股,农业银行3块一股。如果你直接用价格做分析,茅台会把农行压得死死的。这时候就需要标准化。
常用的标准化方法:
| 方法 | 公式 | 特点 |
|---|---|---|
| Z-score标准化 | (x - μ) / σ | 均值为0,标准差为1 |
| Min-Max标准化 | (x - min) / (max - min) | 缩放到[0,1]区间 |
| 百分比变化 | (x_t - x_{t-1}) / x_{t-1} | 转为收益率序列 |
我个人最常用的是Z-score标准化,因为它保留了数据的分布形态。代码实现:
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
df['Close_scaled'] = scaler.fit_transform(df[['Close']])
print(df[['Close', 'Close_scaled']].head())
2.4 完整的数据处理流程
说了这么多,咱们把整个流程串起来。下面这张图展示了数据获取到清洗再到标准化的完整链路:
说白了,数据清洗就是个体力活,但也是最重要的活。我见过太多人花90%的时间写策略,结果数据一塌糊涂,回测结果根本不可信。反过来,把数据搞干净了,哪怕用最简单的均线策略,也能跑出靠谱的结果。
好了,数据这块咱们就聊到这儿。记住一句话:垃圾进,垃圾出。数据质量决定了你策略的天花板。
公众号:蓝海数据掘金营,微信deep3321