第三章:金融数据获取——数据源选择、清洗与预处理
做量化交易,第一道坎就是数据。
我见过太多人,策略写得天花乱坠,结果数据源选错了,回测跑出来全是幻觉。说白了,数据质量决定了策略的生死。今天咱们就聊聊,怎么搞定金融数据获取这件事。
3.1 数据源选择:三个主流方案
我个人习惯把数据源分成三类:免费API、付费API、本地文件。每个都有它的适用场景,别盲目追求高大上。
3.1.1 Yahoo Finance
这是入门首选。免费、易用、覆盖全球市场。我在项目中经常用它做快速原型验证。
优点: 免费、无需API Key、支持历史数据和实时数据
缺点: 数据偶尔延迟、部分市场覆盖不全、有请求频率限制
# 使用 yfinance 库获取数据
import yfinance as yf
# 获取苹果公司股票数据
aapl = yf.download('AAPL', start='2023-01-01', end='2023-12-31')
print(aapl.head())
我的经验: Yahoo Finance 适合做日频数据。如果你需要分钟级数据,它就不太靠谱了。我曾经用它做日内策略回测,结果发现数据有大量缺失,后来果断换了方案。
3.1.2 Alpha Vantage
这个API比Yahoo Finance更专业一些。它提供20多种技术指标,还有外汇、加密货币数据。
# Alpha Vantage 示例
import requests
API_KEY = 'your_api_key_here'
symbol = 'IBM'
url = f'https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol={symbol}&apikey={API_KEY}'
response = requests.get(url)
data = response.json()
注意: Alpha Vantage 免费版每分钟只能请求5次。我刚开始用的时候没注意,结果策略跑着跑着就报错了。建议加个请求间隔控制。
3.1.3 本地CSV文件
这是最稳妥的方式。数据在自己手里,想怎么处理都行。我一般会把从各个渠道获取的数据统一存成CSV格式,方便后续处理。
# 读取本地CSV
import pandas as pd
df = pd.read_csv('stock_data.csv', parse_dates=['Date'], index_col='Date')
print(df.info())
3.2 数据清洗与预处理
拿到原始数据后,千万别直接拿去跑策略。你想想看,数据里可能藏着各种坑:空值、异常值、格式错误……
3.2.1 数据格式统一
不同数据源的格式可能不一样。我习惯把所有数据统一成标准格式:日期作为索引,列名统一为Open、High、Low、Close、Volume。
# 统一数据格式
def standardize_data(df):
df.columns = [col.capitalize() for col in df.columns]
df.index = pd.to_datetime(df.index)
return df.sort_index()
3.2.2 缺失值处理
缺失值是个大问题。我遇到过最夸张的情况,某只股票连续三天没有交易数据,结果策略直接崩了。
常用处理方法:
- 向前填充: 用上一个有效值填充,适合非交易日的缺失
- 向后填充: 用下一个有效值填充,适合数据延迟的情况
- 插值法: 线性插值或多项式插值,适合短期缺失
- 直接删除: 缺失比例小于5%时可以考虑
# 缺失值处理示例
# 向前填充
df.fillna(method='ffill', inplace=True)
# 线性插值
df.interpolate(method='linear', inplace=True)
# 检查缺失值
print(df.isnull().sum())
3.2.3 异常值检测
异常值比缺失值更隐蔽。我记得有一次回测收益特别高,结果发现是数据里混了一个价格异常点——某天股价突然涨了1000倍,显然是数据录入错误。
我的检测方法:
- Z-score方法: 超过3个标准差视为异常
- IQR方法: 低于Q1-1.5*IQR或高于Q3+1.5*IQR视为异常
- 百分比变化法: 日收益率超过±20%需要警惕
# 异常值检测示例
import numpy as np
# 计算日收益率
df['Return'] = df['Close'].pct_change()
# 标记异常值(超过3个标准差)
mean_return = df['Return'].mean()
std_return = df['Return'].std()
df['Anomaly'] = np.abs(df['Return'] - mean_return) > 3 * std_return
# 查看异常值
print(df[df['Anomaly'] == True])
3.3 数据预处理流程
嗯,这里要注意。数据预处理不是一次性工作,而是个迭代过程。我一般按这个流程走:
- 数据加载: 从数据源读取原始数据
- 格式检查: 确认日期格式、列名、数据类型
- 缺失值处理: 根据缺失比例选择合适方法
- 异常值检测: 标记并处理异常点
- 数据对齐: 多只股票数据按日期对齐
- 数据保存: 清洗后的数据存为本地文件
避坑指南: 我曾经犯过一个错误——先做异常值处理再做缺失值填充。结果异常值被填充掩盖了,导致策略在真实交易中频繁出错。正确的顺序应该是:先检测异常值,再处理缺失值。
3.4 知识体系图
3.5 实战建议
最后,分享几个我在实战中总结的经验:
- 数据备份: 每次清洗前都保留原始数据副本。我吃过这个亏,清洗错了数据,想恢复都来不及。
- 自动化脚本: 把数据获取和清洗流程写成脚本,每天定时运行。手动操作太容易出错了。
- 数据验证: 清洗完成后,做个简单的统计验证。比如检查价格是否为正数、成交量是否合理。
- 版本控制: 用Git管理数据清洗脚本,方便回溯和协作。
一个小技巧: 我习惯在数据清洗脚本里加个日志功能,记录每次清洗的改动。这样出了问题,能快速定位是哪个环节导致的。
数据获取和清洗,听起来枯燥,但这是量化交易的地基。地基不稳,楼盖得再高也是白搭。希望这些经验能帮你少走些弯路。